美文网首页
vue2响应式原理

vue2响应式原理

作者: storyWrite | 来源:发表于2021-11-07 20:50 被阅读0次

vue2响应式原理

 /*
 * @Author: dezhao.zhao@hand-china.com
 * @Date: 2021-08-28 16:57:47
 * @Description:
 */

class Dep {
  constructor() {
    // 依赖保存器
    this.subscribers = new Set();
  }
  // 收集依赖
  depend = () => {
    if (activeEffect) {
      this.subscribers.add(activeEffect);
    }
  };
  // 通知收集的依赖
  notify = () => {
    this.subscribers.forEach((effect) => {
      effect();
    });
  };
}
// 用于保存依赖数据结构.....
// weakmap 对于对象的引用为弱引用,当外界不再对存储对象进行引用,weakmap中存储的对象会被回收
const targetMap = new WeakMap();

function getDep(target, key) {
  // 根据target对象取出对应的map对象
  let depsMap = targetMap.get(target);
  if (!depsMap) {
    depsMap = new Map();
    targetMap.set(target, depsMap);
  }
  // 取出具体的dep对象
  let dep = depsMap.get(key);
  if (!dep) {
    dep = new Dep();
    depsMap.set(key, dep);
  }
  return dep;
}

// 响应式系统处理
function reactive(raw) {
  // 将传入对象的每个key都加入响应式系统中
  Object.keys(raw).forEach((key) => {
    const dep = getDep(raw, key);
    let value = raw[key];
    Object.defineProperty(raw, key, {
      get() {
        // 保存依赖
        dep.depend();
        return value;
      },
      set(newValue) {
        if (value !== newValue) {
          // raw[key] = newValue 会导致递归 这里设置以及返回的数据都是value 不能直接对raw操作 会导致死循环递归调用
          value = newValue;
          dep.notify();
        }
      }
    });
  });
  return raw;
}
// 用于临时保存 依赖函数
let activeEffect = null;

//
function watchEffect(effect) {
  // 保存依赖了变量的函数或其他表达式
  activeEffect = effect;
  // 默认 首次执行依赖,且必须执行,如果不执行,不触发get 无法添加依赖
  // 执行effect时就会访问对象属性,此时会把依赖的函数或表达式加入依赖收集中
  effect();
  // 恢复依赖收集,以便下次依赖添加
  activeEffect = null;
}

const info = reactive({ name: 'zdz', age: 18 });
const info1 = reactive({ height: 1.88 });

watchEffect(function () {
  console.log('watch1', info.name);
});
watchEffect(function () {
  console.log('watch2', info.age);
});

watchEffect(function () {
  console.log('watch3', info1.height);
});

info.name = 'newzdz';
info.age = 19;
info1.height = 2.0;

  • 当修改响应式对象中的值时,添加了监听的都会重新执行
  • 第一次watch1-3为首次添加监听执行,第二次为对象属性值变化响应式通知


    image.png

相关文章

网友评论

      本文标题:vue2响应式原理

      本文链接:https://www.haomeiwen.com/subject/ngqyzltx.html