您的位置 首页 技术专栏

解析vue3响应式原理以及api编写

24小时课堂在线收录解析vue3响应式原理以及api编写,前言vue3响应式原理加api编写,快速明白vue3响应式原理GitHub博客:https://github.com/jiejiangzi/…感谢您关注解析vue3响应式原理以及api编写。

前言

vue3响应式原理加api编写,快速明白vue3响应式原理

GitHub博客:https://github.com/jiejiangzi/blog/issues/8

vue3响应式原理实现

先写一段代码看下

实现effect

var name = ‘sl’, age = 22;effect1 = () => `我叫${name},今年${age}岁`effect2 = () => `我叫${name},今年${age+1}岁`console.log(effect1()) //我叫sl,今年22岁console.log(effect2()) //我叫sl,今年23岁age = 30;console.log(effect1()) //我叫sl,今年30岁console.log(effect2()) //我叫sl,今年31岁

看看有什么可以优化的点呢?

首先:多个函数,在age发生变化后需要手动再次调用多个函数才可以获取最新信息

期望可以修改信息以后自动调用多个函数

如何实现呢

可以想到将多个函数存放到一起存放到gather函数,并且让age发生变化时可以将多个函数调用trigger调用

实现gather及trigger

var name = “sl”, age = 22;var tom, joy;effect1 = () => (tom = `我叫${name},今年${age}岁`);effect2 = () => (joy = `我叫${name},今年${age + 1}岁`);var dep = new Set();function gather() { dep.add(effect1); dep.add(effect2);}function trigger() { dep.forEach((effect) => effect());}gather();effect1()effect2()console.log(tom); //我叫sl,今年22岁console.log(joy); //我叫sl,今年23岁age = 30;trigger()console.log(tom); //我叫sl,今年30岁console.log(joy); //我叫sl,今年31岁

再继续看下还是有什么可以优化的点

如果变量是一个对象或多个对象的话该怎么处理呢

变量为原始类型时Set存储

变量为对象时可以用map存储

多个对象时用weakMap存储

var obj1 = { name: “tom”, age: 22 };var obj2 = { name: “joy”, age: 23 };var tom, joy;effect1 = () => (tom = `我叫${obj1.name},今年${obj1.age}岁`);effect2 = () => (joy = `我叫${obj2.name},今年${obj2.age}岁`);var depsMap = new WeakMap();function gather(target, key) { let depMap = depsMap.get(target); if (!depMap) { depsMap.set(target, (depMap = new Map())); } let dep = depMap.get(key); if (!dep) { depMap.set(key, (dep = new Set())); } if (target === obj1) { dep.add(effect1); } else { dep.add(effect2); }}function trigger(target, key) { let depMap = depsMap.get(target); if (depMap) { const dep = depMap.get(key); if (dep) { dep.forEach((effect) => effect()); } }}gather(obj1, “age”);//收集依赖gather(obj2, “age”);//收集依赖effect1();effect2();console.log(tom); //我叫sl,今年22岁console.log(joy); //我叫sl,今年23岁obj1.age = 30;obj2.age = 10;trigger(obj1, “age”);trigger(obj2, “age”);console.log(tom); //我叫sl,今年30岁console.log(joy); //我叫sl,今年31岁

在继续看看有哪些可以优化的点

上边依赖的收集gather以及函数的更新通知trigger每次都是手动收集手动触发更新,那有什么方法可以自动收集及触发吗

Proxy

实现reactive

先写一个reactive函数

function reactive(target) { const handle = { set(target, key, value, receiver) { Reflect.set(target, key, value, receiver); trigger(receiver,key) // 设置值时触发自动更新 }, get(target, key, receiver) { gather(receiver, key); // 访问时收集依赖 return Reflect.get(target, key, receiver); }, }; return new Proxy(target, handle);}

然后将reactive函数应用到之前代码

var obj1 = reactive({ name: “tom”, age: 22 });var obj2 = reactive({ name: “joy”, age: 23 });var tom, joy;effect1 = () => (tom = `我叫${obj1.name},今年${obj1.age}岁`);effect2 = () => (joy = `我叫${obj2.name},今年${obj2.age}岁`);var depsMap = new WeakMap();function gather(target, key) { let depMap = depsMap.get(target); if (!depMap) { depsMap.set(target, (depMap = new Map())); } let dep = depMap.get(key); if (!dep) { depMap.set(key, (dep = new Set())); } if (target === obj1) { dep.add(effect1); } else { dep.add(effect2); }}function trigger(target, key) { let depMap = depsMap.get(target); if (depMap) { const dep = depMap.get(key); if (dep) { dep.forEach((effect) => effect()); } }}effect1();effect2();console.log(tom); //我叫sl,今年22岁console.log(joy); //我叫sl,今年23岁obj1.age = 30;obj2.age = 10;console.log(tom); //我叫sl,今年30岁console.log(joy); //我叫sl,今年31岁

然后还有个问题,就是gather函数中有写死dep添加函数

如何解决呢 重写effect函数

let activeEffect = nullfunction effect(fn) { activeEffect = fn; activeEffect(); activeEffect = null; // 执行后立马变成null}var depsMap = new WeakMap();function gather(target, key) { // 避免例如console.log(obj1.name)而触发gather if (!activeEffect) return; let depMap = depsMap.get(target); if (!depMap) { depsMap.set(target, (depMap = new Map())); } let dep = depMap.get(key); if (!dep) { depMap.set(key, (dep = new Set())); } dep.add(activeEffect) //将函数添加到依赖}effect(effect1);effect(effect2);

reactive也已经实现了,那么还有ref也实现下

ref

在vue3中ref怎么使用呢

var name = ref(‘tom’)console.log(name.value) // tom

需要使用.value的方式获取值

function ref(name){ return reactive( { value: name } )}const name = ref(‘tom’);console.log(name.value) //tom

完整代码

var activeEffect = null;function effect(fn) { activeEffect = fn; activeEffect(); activeEffect = null; }var depsMap = new WeakMap();function gather(target, key) { // 避免例如console.log(obj1.name)而触发gather if (!activeEffect) return; let depMap = depsMap.get(target); if (!depMap) { depsMap.set(target, (depMap = new Map())); } let dep = depMap.get(key); if (!dep) { depMap.set(key, (dep = new Set())); } dep.add(activeEffect)}function trigger(target, key) { let depMap = depsMap.get(target); if (depMap) { const dep = depMap.get(key); if (dep) { dep.forEach((effect) => effect()); } }}function reactive(target) { const handle = { set(target, key, value, receiver) { Reflect.set(target, key, value, receiver); trigger(receiver, key); // 设置值时触发自动更新 }, get(target, key, receiver) { gather(receiver, key); // 访问时收集依赖 return Reflect.get(target, key, receiver); }, }; return new Proxy(target, handle);}function ref(name){ return reactive( { value: name } )}

以上就是解析vue3响应式原理以及api编写的详细内容,更多请关注24小时课堂在线其它相关文章!

本文来自网络,不代表24小时课堂在线立场,转载请注明出处:https://www.24ketang.cn/99471.html

为您推荐

返回顶部