vue3 相比于 vue2 有了显著的性能晋升,而最间接的就是从 Object.defineProperty 换成了 proxy 做数据劫持,而 effect 是响应式零碎的外围,响应式零碎又是 vue3 中的外围。
最根本的响应式就是我扭转一个值,另一个值也主动做出变动。
此时咱们执行一下文件会看到达到了咱们想要的目标。当然这并不是咱们最终想要的,咱们看一下 vue3 是如何做的。
在 vue3 中 reactivity 能够作为一个独自的模块下载。
effect 函数执行了两次,在第一次传入匿名函数的时候执行了一次 在之后 a 变量的值发生变化的时候又执行了一次。
当初咱们本人来实现一个响应式零碎。
响应式最重要的就是收集依赖和触发依赖。
1. 创立一个类用来收集和触发依赖
2. 在申明变量时触发收集操作
这时候就和 vue3 中的 ref 很像了。当初能够优化一下。将在收集依赖时手动调用 depend 办法改为在 get 办法中调用,在变量从新赋值时手动调用 notice 办法改为在 set 中调用。
3. 创立一个 reactive 函数,return 一个 Proxy 对象
在 Proxy 中应用 get 来拦挡取值行为并 return 出对应后果。这里咱们应用的是 ES6 新的 Reflect 函数。相干文档点击这里,总之 Reflect.get(target,key) 相当于 target[key]。
4. 创立全局 map 用于存储所有的对象与依赖关系
5. 设置 set 办法拦挡赋值行为并触发依赖
6. 应用 effectWatch 办法保留依赖
这就实现了一个根本的 reactive 办法,实现了响应式关系。
全副代码:
// let a = 10;
// let b;
// update()
// function update() {
// b = a + 10;
// console.log(b)
// }
// a = 20;
// update();
// vue3 的 reactivity 模块
// const {reactive, effect} = require("@vue/reactivity");
// let a = reactive({
// value: 10,
// });
// let b;
// effect(() => {
// b = a.value + 10;
// console.log(b);
// });
// a.value = 20;
// 响应式库
let currentEffect; // 全局依赖
class Dep {constructor(val) {this.effects = new Set(); // 依赖列表
this._val = val;
}
get value() {this.depend();
return this._val;
}
set value(newVal) {
this._val = newVal
this.notice()}
// 收集依赖
depend() {if (currentEffect) this.effects.add(currentEffect)
}
// 触发依赖
notice() {this.effects.forEach((effect) => {effect()
})
}
}
// 收集依赖
function effectWatch(effect) {
currentEffect = effect;
// 绑定依赖时先触发一次依赖
effect();
currentEffect = null;
}
// const dep = new Dep(10)
// let b;
// effectWatch(() => {
// b = dep.value + 10;
// console.log(b)
// })
// dep.value = 20;
// vue3 proxy
const targetMap = new Map(); // 存储所有的依赖映射关系
function getDepta(target, key) {let depsMap = targetMap.get(target) // 获取对象的所有依赖
if (!depsMap) {depsMap = new Map()
targetMap.set(target, depsMap)
}
let dep = depsMap.get(key) // 获取对应 key 的所有依赖
if (!dep) {dep = new Dep();
depsMap.set(key, dep)
}
return dep;
}
function reactive(obj) {
return new Proxy(obj, {get(target, key) {const dep = getDepta(target, key);
dep.depend() // 收集依赖
return Reflect.get(target, key)
},
set(target, key, value) {const dep = getDepta(target, key);
const relust = Reflect.set(target, key, value)
// 触发依赖
dep.notice();
return relust;
}
})
}
const user = reactive({
age: 19,
aaa: 30
})
let b, c;
effectWatch(() => {console.log('reactive')
b = user.age + 10
console.log(b)
})
effectWatch(() => {console.log('reactive1111')
c = user.aaa - 5
console.log(c)
})
user.age = 20
user.aaa = 20