乐趣区

关于vue.js:Vue3中是如何实现数据响应式

副作用函数:指的是会产生副作用的函数;

JavaScript
let val = 1;// 全局变量
function effect() {val = 2; // 批改全局变量,产生副作用}

effect 函数执行时,对全局变量 val 产生了副作用,扭转了其值。

响应式数据:

const obj = {text:"hello world"};
function effect(){
  //effect 函数的执行读取 obj.text
  document.body.innerHTML = obj.text;
}
obj.text = "hello Vue.js";

下面的副作用函数 effect 会设置 bodyinnerText属性,其值为 obj.text, 第 6 行代码又批改了text 的值,冀望副作用函数从新执行,如果能实现这个指标,那么对于 obj 就是响应式数据。

如何能力让 obj 变成响应式数据呢?通过观察咱们发现了两点线索:

▪当副作用函数 effect 执行时,会触发字段 obj.text读取 操作;

▪当批改 obj.text 的值时,会触发字段 obj.text设置 操作;

  如果可能拦挡 obj 对象的 读取 设置 操作,事件就迎刃而解了。当读取字段 obj.text 时,咱们能够把 副作用 函数存储到一个“”中。

  当设置 obj.text 时,再把副作用函数 effect 从“桶”里取出并执行。

  依照下面的思路,应用 Proxy 来实现:

// 创立一个副作用函数的桶
 const bucket = new Set();
 
 // 原始数据
 const data = {text: "hello world"};
 
 // 对原始数据的代理
 const obj = new Proxy(data, {
   // 拦挡读取操作
   get(traget, key) {
     // 将副作用函数 effect 增加到副作用函数的桶中
     bucket.add(effect);
     // 返回属性值
     return traget[key];
   },
   // 拦挡设置操作
   set(traget, key, newValue) {
     // 设置属性值
     traget[key] = newValue;
     // 把副作用函数从桶中取出来并执行
     bucket.forEach((fn) => fn());
     // 返回 true 代表设置操作胜利
     return true;
   },
 });
 

测试用例:

  function effect() {document.body.innerHTML = obj.text;}
  effect();
  setTimeout(() => {obj.text = "hello vue3";}, 1000);

目前的实现数据响应式还存在很多缺点,比方副作用函数的名字是写死的,下一章将欠缺响应式零碎。

退出移动版