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 proxyconst 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 = 20user.aaa = 20