proxy响应式原理demo

157 阅读3分钟

把proxy处理封装一个reactive函数

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vite App</title>
  </head>

  <body>
    <div id="app"></div>
    <script>
      function isObject(data) {
        return typeof data === "object" && data !== null;
      }
      function reactive(data) {
        if (isObject(data)) {
          return new Proxy(data, {
            get(target, key) {
              console.log("get访问", key, target[key]);
              return target[key];
            },
            set(target, key, value) {
              console.log("set 修改", key, value);
              target[key] = value;
            },
          });
        }
      }
      let states = { name: "xiaoming" };

      let p = reactive(states);
      p.name
      p.name = "xiaoxiao";
    //   get访问 name xiaoming
    //  set 修改 name xiaoxiao
    </script>
  </body>
</html>

proxy 执行多个副作用函数

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vite App</title>
  </head>

  <body>
    <div id="app"></div>
    <script>
      function isObject(data) {
        return typeof data === "object" && data !== null;
      }
      function reactive(data) {
        if (isObject(data)) {
          return new Proxy(data, {
            get(target, key) {
              console.log("get访问", key);
              return target[key];
            },
            set(target, key, value) {
              console.log("set 修改", key, value);
              target[key] = value;
            },
          });
        }
      }
      let states = { name: "xiaoming" };
      let p = reactive(states);
      // 执行多个副作用函数
      function effect() {
        console.log("执行副作用函数1");
        p.name; //读取
      }
      effect();
      // 执行多个副作用函数
      function effect2() {
        console.log("执行副作用函数2");
        p.name; //读取
      }
      effect2();

      setTimeout(() => {
        p.name = "xiaoxiao"; //修改
      }, 2000);
      
        执行副作用函数1
        get访问 name
         执行副作用函数2
         get访问 name
         set 修改 name xiaoxiao
    </script>
  </body>
</html>

proxy代理 用set集合执行多个副作用函数 为了去重

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vite App</title>
  </head>

  <body>
    <div id="app"></div>
    <script>
      let bucket = new Set(); // 去重
      function isObject(data) {
        return typeof data === "object" && data !== null;
      }
      function reactive(data) {
        if (isObject(data)) {
          return new Proxy(data, {
            get(target, key) {
              console.log("get访问", key);
              return target[key];
            },
            set(target, key, value) {
              console.log("set 修改", key, value);
              target[key] = value;
              bucket.forEach((fn) => fn()); // 执行副作用函数
            },
          });
        }
      }
      let states = { name: "xiaoming", age: 18 };
      let p = reactive(states);
      // 执行多个副作用函数
      function effect() {
        console.log("执行副作用函数1");
        p.name; //读取
      }
      bucket.add(effect);
      bucket.add(effect);
      // 执行多个副作用函数
      function effect2() {
        console.log("执行副作用函数2");
        p.age; //读取
      }
      bucket.add(effect2);

      setTimeout(() => {
        p.name = "xiaofei"; //修改
      }, 1000);
    </script>
  </body>
</html>

proxy代理map解决一个属性访问多个副作用

9deae57e2fa2b8c4c6379d5c6b55897.jpg

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vite App</title>
  </head>

  <body>
    <div id="app"></div>
    <script>
      let bucket = new Map(); //map结构 [name:[effect1,effect2],age:[effect1,effect2]]
      let activeEffect = null; // 当前执行的副作用函数
      function isObject(data) {
        return typeof data === "object" && data !== null;
      }
      // 封装执行多个副作用函数
      function effect(fn) {
        activeEffect = fn;
        fn();
        activeEffect = null;
      }
      // 依赖收集
      function track(target, key) {
        if (activeEffect) {
          let depSet = new Set(); // 解决多个
          if (!bucket.get(key)) {
            //获取对应的映射
            bucket.set(key, depSet);
          }

          depSet.add(activeEffect);
        }
      }
      // 触发依赖
      function trigger(target, key) {
        let depSet = bucket.get(key);
        console.log(depSet);
        if (depSet) {
          depSet.forEach((fn) => fn());
        }
      }

      function reactive(data) {
        if (isObject(data)) {
          return new Proxy(data, {
            get(target, key) {
              // console.log('get访问',key)
              track(target, key);
              return target[key];
            },
            set(target, key, value) {
              console.log("set 修改", key, value);
              target[key] = value;
              trigger(target, key);
              return true;
            },
          });
        }
      }
      let states = { name: "xiaoming", age: 18 };
      let p = reactive(states);
      // 执行多个副作用函数

      effect(() => {
        console.log("执行副作用函数2", p.age);
      });
      effect(() => {
        console.log("执行副作用函数3", p.age);
      });

      // setTimeout(()=>{
      //     p.name='xiaofei' //修改
      // },1000)
    </script>
  </body>
</html>

proxy代理weakmap创建多个对象方法同一个属性

d7fc27e0ae3fc95e04875cc04f66fba.jpg

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vite App</title>
  </head>

  <body>
    <div id="app"></div>
    <script>
      let bucket = new WeakMap(); //WeakMap结构 [state: Map[name:set[effect1,effect2],age:set[effect1,effect2]]]
      let activeEffect = null; // 当前执行的副作用函数
      function isObject(data) {
        return typeof data === "object" && data !== null;
      }
      // 封装执行多个副作用函数
      function effect(fn) {
        activeEffect = fn;
        fn();
        activeEffect = null;
      }
      // 依赖收集
      function track(target, key) {
        if (activeEffect) {
          let depMap = bucket.get(target);
          if (!depMap) {
            depMap = new Map();
            bucket.set(target, depMap);
          }
          let depSet = depMap.get(key); // 解决多个
          if (!depSet) {
            //获取对应的映射
            depSet = new Set();
            depMap.set(key, depSet);
          }

          depSet.add(activeEffect);
        }
      }
      // 触发依赖
      function trigger(target, key) {
        let depMap = bucket.get(target);
        if (!depMap) return;

        let depSet = depMap.get(key);
        if (depSet) {
          depSet.forEach((fn) => fn());
        }
      }

      function reactive(data) {
        if (isObject(data)) {
          return new Proxy(data, {
            get(target, key) {
              // console.log('get访问',key)
              track(target, key);
              return target[key];
            },
            set(target, key, value) {
              console.log("set 修改", key, value);
              target[key] = value;
              trigger(target, key);
              return true;
            },
          });
        }
      }
      let p = reactive({ name: "xiaoming", age: 18 });
      let p2 = reactive({ name: "xiaoming2", age: 18 });
      // 执行多个副作用函数

      effect(() => {
        console.log("执行副作用函数2", p.age);
      });
      effect(() => {
        console.log("执行副作用函数3", p2.age);
      });
      console.log(bucket);
      setTimeout(() => {
        p.name = "xiaofei"; //修改
      }, 1000);
    </script>
  </body>
</html>