vue3响应式原理

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  vue3兼容性只到ie11,如果监测到vue3无法兼容,会自动优雅降级到vue2
  <script>
    // vue3中的响应式原理,利用Proxy对象对数据拦截
    // 如何避免重复代理
    const toProxy = new WeakMap() //形如 obj:observed
    const toRow = new WeakMap() //形如 observed:obj


    function isObject(obj){
      return typeof obj === 'object' || obj === null
    }
    function reactive(obj){
      if(!isObject(obj)){
        return
      }

      // 查找缓存
      if(toProxy.has(obj)){
        return toProxy.get(obj)
      }
      // 传入的obj就是代理对象,此时不用反复代理
      if(toRow.has(obj)){
        return obj
      }

      const observed = new Proxy(obj,{
        // 属性的增删改查都涉及到了
        get(target,key,receiver){
          // 优雅的获取值
          const res = Reflect.get(target,key,receiver)
          console.log(`获取${key}:${res}`);
          // 运行时递归,相比于初始化递归,性能较好
          return isObject(res) ? reactive(res) : res
        },
        set(target,key,val,receiver){
          // 返回bool
          const res = Reflect.set(target,key,val,receiver)
          console.log(`设置${key}:${res}`);
          return res
        },
        deleteProperty(target,key){
          const res = Reflect.deleteProperty(target,key)
          console.log(`删除${key}`);
          return res
        },
      })

      // 缓存
      toProxy.set(obj,observed)
      toRow.set(observed,obj)

      return observed
    }

    const data = {foo:'foo',bar:{a:1},arr:[1,2,3]}
    const react = reactive(data)
    // 1获取
    // react.foo
    // 2设置已存在属性
    // react.foo = 'fooooooo'
    // 3设置不存在属性
    // react.name = 'zhongwuhuang'
    // 4嵌套对象设置
    react.bar.a = 10
    react.bar.a
    // 操作数组
    // react.arr[0] = 10
    // react.arr

    // 时候是否缓存成功
    // console.log(react === reactive(data));
    


  </script>
</body>
</html>
原文地址:https://www.cnblogs.com/zwhbk/p/12431470.html