VUE 2.x的响应式原理模型

本文深入探讨了Vue3中的响应式原理,通过一个实例展示了如何使用JavaScript实现数据劫持来监听和拦截数组方法,如push、pop等。通过reactify函数将数据转换为响应式,当数组方法被调用时,会打印出相应的操作信息,并确保数据的更新。这种方法有助于理解Vue3中Proxy如何解决数组操作的响应式问题。
摘要由CSDN通过智能技术生成

先把结果展示出来:(整个实现的源代码在下面,拿去试试)

在这里插入图片描述
在这里插入图片描述

<!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>
    <script>
      let ARRAY_METHODS = [
        "push",
        "pop",
        "shift",
        "unshift",
        "reverse",
        "sort",
        "splice",
      ];

      //   此方法仍然无法解决操作数组长度length属性的响应式问题 vue3的proxy 可以解决  替代方法:splice(0)
      let array_methods = Object.create(Array.prototype);
      ARRAY_METHODS.forEach((method) => {
        array_methods[method] = function () {
          console.log(`当前正在使用的是拦截后的方法:${method}`);
          for (var i = 0; i < arguments.length; i++) {
            reactify(arguments[i]);
          }
          let res = Array.prototype[method].apply(this, arguments);
          return res;
        };
      });

      // 劫持数据
      function defineReactive(target, key, value, enumerable) {
        Object.defineProperty(target, key, {
          configurable: true,
          enumerable: !!enumerable,
          get() {
            console.log(`读取${key}属性当前值为${value}`);
            return value;
          },
          set(newVal) {
            console.log(`设置${key}属性,改为:${newVal}`);
            value = newVal;
          },
        });
      }

      //  数据响应式化处理
      function reactify(o) {
        let keys = Object.keys(o);
        for (var i = 0; i < keys.length; i++) {
          let key = keys[i];
          let val = o[key];
          if (Array.isArray(o[key])) {
            val.__proto__ = array_methods; // 使用前文中的js劫持策略且只重写需要要改为响应式数组的原型方法 
            for (var j = 0; j < val.length; j++) {
              reactify(val[j]);
            }
          } else {
            defineReactive(o, key, val, true); // 数据劫持并响应式处理
          }
        }
      }

      //   数据源
      let data = {
        name: "zachary",
        age: 18,
        hobits: [{ title: "爬山" }, { title: "游泳" }, { title: "电子游戏" }],
      };
      reactify(data);
    </script>
  </body>
</html>
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值