Vue3.0 响应式系统(二)

上一篇文章分析了用Proxy代理问题,用户需要自己对原始对象数据进行深度代理,这一篇文章看看还有没有其他问题。先看一个例子:

​
<html>
  <head>
    <style type="text/css"></style>
  </head>
  <body>
    <script>
      let arr = [
        {
          id: 1,
          msg: "arr_1",
        },
        {
          id: 2,
          msg: "arr_2",
        },
      ];      
      let arrProxy = new Proxy(arr, {
        get(target, key, receiver) {
          console.log(`arrProxy get key: ${key}`);
          return Reflect.get(target, key, receiver);
        },
        set(target, key, value, receiver) {          
          console.log(`arrProxy set key: ${key}, value: ${JSON.stringify(value)}`);            
          return Reflect.set(target, key, value, receiver);
        },
      });

      arrProxy.unshift({
        id: 0,
        msg: 'arr_0'
      })
    </script>
  </body>
</html>

这个例子对数组进行了Proxy代理。当在这个数组开始处增加一个元素时,我们看看打印结果:

get触发了多次,set也触发了多次。set为什么会触发多次呢?在数组最前面插入元素,依次会把数组之前的元素往后挪,最后把要插入的元素放到最开始处,最后还更新了length值,所以触发了多次set操作。我们想要的set触发后notify一次就好了,有没有办法做到这一点呢? 函数防抖就可以了,我们用setTimeout 处理一下这个抖动,代码如下:

​
<html>
  <head>
    <style type="text/css"></style>
  </head>
  <body>
    <script>
      let arr = [
        {
          id: 1,
          msg: "arr_1",
        },
        {
          id: 2,
          msg: "arr_2",
        },
      ];
      let timerId = 0
      let arrProxy = new Proxy(arr, {
        get(target, key, receiver) {
          console.log(`arrProxy get key: ${key}`);
          return Reflect.get(target, key, receiver);
        },
        set(target, key, value, receiver) {          
          clearTimeout(timerId)
          timerId = setTimeout(() => {
            console.log(`arrProxy set key: ${key}, value: ${JSON.stringify(value)}`);  
          }, 0);
          return Reflect.set(target, key, value, receiver);
        },
      });

      arrProxy.unshift({
        id: 0,
        msg: 'arr_0'
      })
    </script>
  </body>
</html>

在set中加了防抖处理,看一下打印结果:

把之前触发set后,notify多次的操作都给clear了,最后一个是更新length 操作,被保留下来了。其实这么干不太对,我们期望的是length操作触发set后不去notify,怎么才能做到这一点呢?判断一下key是否为length就可以了。代码如下:

​
<html>
  <head>
    <style type="text/css"></style>
  </head>
  <body>
    <script>
      let arr = [
        {
          id: 1,
          msg: "arr_1",
        },
        {
          id: 2,
          msg: "arr_2",
        },
      ];      
      let arrProxy = new Proxy(arr, {
        get(target, key, receiver) {
          console.log(`arrProxy get key: ${key}`);
          return Reflect.get(target, key, receiver);
        },
        set(target, key, value, receiver) {  
          let isLength = key === 'length' ? true : false
          if(!isLength){   
            console.log(`arrProxy set key: ${key}, value: ${JSON.stringify(value)}`);  
          }          
          return Reflect.set(target, key, value, receiver);
        },
      });

      arrProxy.unshift({
        id: 0,
        msg: 'arr_0'
      })
    </script>
  </body>
</html>

这样当修改length时触发set就不会去notify了。

这个例子我们只是对length简单处理了一下,vue3.0 当然会比这复杂的多。下一篇文章我们就看看Vue3.0 是如何利用 Proxy实现响应式系统的。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值