【Vue】为什么 Vue3 使用 Proxy 代替 defineProperty?

响应式原理:
vue的响应式实现主要是利用了Object.defineProperty的方法里面的setter 与getter方法的观察者模式来实现。
在组件初始化时会给每一个data属性注册getter和setter,然后再new 一个自己的Watcher对象,此时watcher会立即调用组件的render函数去生成虚拟DOM。
在调用render的时候,就会需要用到data的属性值,此时会触发getter函数,将当前的Watcher函数注册进sub里。当data属性发生改变之后,就会遍历sub里所有的watcher对象,通知它们去重新渲染组件。

先来看看 Vue2 中 defineProperty 来操作数据:

const obj = {
  a: 1,
  b: 2,
  c: {
    a: 1,
    b: 2
  }
}
function _isObject(v) {
  return typeof v === 'object' && v !== null;
}
function observe(object) {
  for (let key in object) {
    let v = object[key];
    if (_isObject(v)) {
      observe(v)
    }
    Object.defineProperty(object, key, {
      get() {
        console.log('read ' + key);
        return v;
      },
      set(val) {
        if (val !== v) {
          console.log('change ' + key);
          v = val;
        }
      }
    })
  }
}
observe(obj)
// obj.a = 3;
obj.c.a = 4;

所以 Vue2 的缺陷是无法监听到属性的增加和删除,因为只有 getter 和 setter 函数。此外,还通过深度遍历,有效率的损失,将属性变成 getter 和 setter 函数。

Vue2 缺陷总结:

1、无法监听es6的 Set、Map 变化;
2、无法监听 Class 类型的数据;
3、属性的新增或者删除也无法监听;
4、数组元素的增加和删除也无法监听。


而 Vue3 中Proxy 直接监听整个对象的变化:

const obj = {
  a: 1,
  b: 2,
  c: {
    a: 1,
    b: 2
  }
}
function _isObject(v) {
  return typeof v === 'object' && v !== null;
}
function observe(obj) {
  const proxy = new Proxy(obj, {
    get(target, k) {
      let v = target[k]
      if (_isObject(v)) {
        v = observe(v);
      }
      console.log('read', k)
      return v;
    },
    set(target, k, val) {
      if (target[k] !== val) {
        target[k] = val;
        console.log('change', k)
      }
    }
    // ....

  })
  return proxy;
}

proxy.a = 3;
proxy.aa;

不监听属性,而是监听整个代理对象。只有当读取到对象属性的时候才会进行遍历监听。


总结:

  1. proxy的优势如下:
  • Proxy 可以直接监听对象而非属性,可以直接监听数组的变化;
  • Proxy 有多达 13 种拦截方法,不限于 apply、ownKeys、deleteProperty、has 等等。是Object.defineProperty 不具备的;
  • Proxy 返回的是一个新对象,我们可以只操作新的对象达到目的,而 Object.defineProperty 只能遍历对象属性直接修改;
  1. Object.defineProperty 的优势如下:
  • 兼容性好,支持 IE9,而 Proxy 的存在浏览器兼容性问题,而且无法用 polyfill(垫片)来弥补
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小秀_heo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值