zoukankan      html  css  js  c++  java
  • vue3基础知识学习系列(二)响应式原理实现

    使用对象的 set/get 方法 模拟实现 vue3 ref 单数据响应

    const targetMap = new Map();
    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); // 初始值打印为 10  dep.value修改后打印为 20
    });
    // 值变更 通知 触发依赖 更新变量
    dep.value = 20;
    

    使用 Proxy/Reflect 实现 vue3 reactive 函数的实现原理

    const targetMap = new Map(); //存储指定key的对象
    let currentEffect;
    class Dep {
      constructor(val) {
        this.effects = new Set();
        this._val = val;
      }
      // 收集依赖
      depend() {
        if (currentEffect) {
          this.effects.add(currentEffect);
        }
      }
      // 触发依赖
      notice() {
        this.effects.forEach((effect) => {
          effect();
        });
      }
    }
    function effectWatch(effect) {
      // 依赖收集
      currentEffect = effect;
      effect();
      currentEffect = null;
    }
    
    function getDep(target, key) {
      // key - dep依赖收集
      let depsMap = targetMap.get(target);
      if (!depsMap) {
        depsMap = new Map();
        targetMap.set(target, depsMap);
      }
      let dep = depsMap.get(key);
      if (!dep) {
        dep = new Dep();
        depsMap.set(key, dep);
      }
      return dep;
    }
    function reactive(raw) {
      //代理对象所有属性
      return new Proxy(raw, {
        get(target, key) {
          const dep = getDep(target, key);
          // 依赖收集
          dep.depend();
          return Reflect.get(target, key);
        },
        set(target, key, value) {
          // 触发依赖
          const dep = getDep(target, key);
          const result = Reflect.set(target, key, value);
          dep.notice();
          return result;
        },
      });
    }
    
    const user = reactive({
      age: 19,
    });
    
    let double;
    effectWatch(() => {
      double = user.age;
      console.log(double);
    });
    
    user.age = 20;
    
  • 相关阅读:
    【LeetCode】41. First Missing Positive (3 solutions)
    【LeetCode】42. Trapping Rain Water
    【LeetCode】164. Maximum Gap (2 solutions)
    【原创】SQLServer将数据导出为SQL脚本的方法
    Jconsole远程监控tomcat 的JVM内存(linux、windows)
    selenium + python自动化测试环境搭建
    LR--Controller的Pacing设置(不容忽视的设置)
    loadrunner录制回放常见问题及解决办法
    修改windows系统文件权限
    TestNG官方文档中文版(4)-运行TestNG
  • 原文地址:https://www.cnblogs.com/Lewiskycc/p/14325818.html
Copyright © 2011-2022 走看看