晌应式系统的作用与实现
晌应式数据与副作用函数
首先我们要了解什么是晌应式数据
- 其中晌应式数据为当数据发生改变时会触发与数据绑定对应的操作
- 而副作用函数是当数据发生改变时需要执行的函数称之为副作用函数
晌应式数据的基本实现
当我们要实现一个数据晌应时我们要明白JS能实现哪些操作
- 在JS里每一个对象都有get 与set属性
- 其中get在属性获取时触发
- set在属性改变时触发
let obj = {test: "123"};
obj.test ;
obj.text = 456;
基本晌应式的基本原理
- 晌应式属性触发时我们可以能过一个方法将当前属性对应的副作用函数收集起来
- 当属性改变时我们就可以将收集起来的副作用函数拿出来执行
- 我们可以将收集器比作用一个桶
- 每一个副作用函数相于桶里一个圆盘每增加一个副作用函数桶里的圆盘会增加一层
- 当set 触发时我们将桶里的圆盘一个一个的拿出来执行
在VUE2 中可以通过es2015 中的Object.defineProperty函数实现数据的获取与设置操作,而VUE3则使用es6中的Proxy实现
完整晌应的系统的实现
const bucket = new WeakMap()
const data = {
foo: 1
}
const obj = new Proxy(data, {
get(target, key) {
track(target, key)
return target[key]
},
set(target, key, newVal) {
target[key] = newVal
trigger(target, key)
}
})
function track(target, key) {
let depsMap = bucket.get(target)
if (!depsMap) {
bucket.set(target, (depsMap = new Map()))
}
let deps = depsMap.get(key)
if (!deps) {
depsMap.set(key, (deps = new Set()))
}
deps.add(activeEffect) activeEffect.deps.push(deps)
}
function trigger(target, key) {
const depsMap = bucket.get(target)
if (!depsMap) return
const effects = depsMap.get(key)
const effectsToRun = new Set()
effects && effects.forEach(effectFn => {
if (effectFn !== activeEffect) {
effectsToRun.add(effectFn)
}
})
effectsToRun.forEach(effectFn => effectFn())
}
let activeEffect
const effectStack = []
function effect(fn) {
const effectFn = () => {
cleanup(effectFn)
activeEffect = effectFn
effectStack.push(effectFn);
fn();
effectStack.pop() activeEffect = effectStack[effectStack.length - 1]
}
effectFn.deps = []
effectFn()
}
function cleanup(effectFn) {
for (let i = 0; i < effectFn.deps.length; i++) {
const deps = effectFn.deps[i]
deps.delete(effectFn)
}
effectFn.deps.length = 0;
}
effect(() => {
console.log(99)
obj.foo++
})