Vue3 把实现双向数据绑定的 API Object.defineProperty 换成了 Proxy,出于什么考虑?

核心

  • 主要是处于性能上面的考虑。

  • 如果对象有 100 个属性,Object.defineProperty 要循环 100 次来劫持每一个属性

  • 而由于 Proxy 直接可以代理整个对象,一次就可以搞定,免去了循环100次来劫持每个属性的性能消耗。

  • Object.defineProperty对后面新增的数据无法实现数据的双向绑定,而 Proxy 对后续新增的属性也具有响应式。

接下来给大家从代码,详细分析下两者的区别,性能提高提现在了哪里。

Vue2中的通过Object.defineProperty实现数据的劫持

<!DOCTYPE html>
<html lang="en">

<head>
 <meta charset="UTF-8">
 <meta http-equiv="X-UA-Compatible" content="IE=edge">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <title>Document</title>
</head>

<body>
 <p id="oP"></p>
 <input type="text" id="oInput">
 <script>
   const data = {
     name: '张三丰',
     age: 18,
   };
   // console.log(data)
   // 数据劫持:就是把数据都变成 getter/setter 形式,能做到对数据操作的时候,也能添加一些额外的功能(例如修改视图)
   // 对象、属性、描述/配置
   const copyData = { ...data };
   // ['name', 'age']
   Object.keys(data).forEach(key => {
     Object.defineProperty(data, key, {
       get() {
         // !这儿给了你自由,获取数据的时候想干啥干啥
         // 获取 name 的时候,会触发这儿
         return copyData[key]
       },
       set(newValue) {
         // #1
         oP.innerHTML = newValue
         oInput.value = newValue
         // 设置 name 的时候,会触发这儿
         copyData[key] = newValue
       }
     });
   })
   oInput.oninput = function (e) {
     // 边输入,边设置,边触发 #1 处的 set
     data.name = e.target.value
   }
 </script>
</body>

</html>

从代码中可以看到,Object.defineProperty实现数据的劫持,用到了for循环,也就是说,如果你的数据越大,那么性能消耗的也就随着变大。

Vue3 中的Proxy实现数据的劫持

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <p id="oP"></p>
  <input type="text" id="oInput">
  <script>
    const data = {};

    // proxyData => 代理对象
    // 对代理的操作 proxyData => 会影响到原始值 data
    const proxyData = new Proxy(data, {
      get(target, attr) {
        // 获取数据的时候会触发这儿
        // target => 原数据
        // attr => 属性
        // console.log(target === data)
        return target[attr]
      },
      set(target, attr, newValue) {
        oP.innerHTML = newValue
        oInput.value = newValue
        // 设置数据的时候会触发这儿
        target[attr] = newValue
      }
    })
    oInput.oninput = function (e) {
      proxyData.address = e.target.value
    }
  </script>
</body>

</html>

总结:

  • 两者对比,不难看出,两者的数据劫持都用到了set和get的方法,但是明显可以看出来,Proxy中的数据劫持,并没有用到循环,也就是性能上面的一个提升。
  • Proxy中他劫持的是整个对象,包含了后面新增的一些属性,也能够实现数据的响应式变化,而Object.defineProperty是通过循环遍历的原来对象的键,因此后面加进来的属性,无法实现响应式的变化。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值