千家信息网

vue3响应式原理和api编写的方法是什么

发表于:2024-09-28 作者:千家信息网编辑
千家信息网最后更新 2024年09月28日,这篇文章主要讲解了"vue3响应式原理和api编写的方法是什么",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"vue3响应式原理和api编写的方法是什么
千家信息网最后更新 2024年09月28日vue3响应式原理和api编写的方法是什么

这篇文章主要讲解了"vue3响应式原理和api编写的方法是什么",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"vue3响应式原理和api编写的方法是什么"吧!

前言

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


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编写的方法是什么"的内容了,经过本文的学习后,相信大家对vue3响应式原理和api编写的方法是什么这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是,小编将为大家推送更多相关知识点的文章,欢迎关注!

0