乐趣区

关于vue.js:vue3reactivity响应式

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
退出移动版