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
发表回复