Vue3 响应式系统 - 4 - object的响应式方案

文章详细介绍了JavaScript中的Proxy和Reflect对象的使用,包括如何通过Proxy创建代理对象来拦截和重定义基本操作,以及Reflect作为默认行为的全局对象。接着,文章探讨了响应式数据的实现,解释了Reflect.get方法和receiver参数在响应式系统中的作用,并展示了如何处理如in操作符和for...in循环等非标准get操作。最后,文章讨论了如何处理对象的深度响应,确保嵌套属性的变更也能触发响应式更新。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 理解Proxy和Reflect

使用Proxy可以创建一个代理对象,允许对被代理对象的基本操作进行拦截并重新定义。

const proxyData = new Proxy(data, {
  get(target, key, receiver) {
    …
  },
  set(target, key, newVal, receiver) {
    …
  }
})

如上代码所示,Proxy对象接受两个参数,一个是data对象,第二个是参数是个对象,这个对象中包含了各种函数,比如其中的get用来拦截数据的读取操作,set用来拦截数据的赋值操作。

在js中函数也是一种对象,函数的调用也可以使用Proxy拦截器中apply函数来拦截。

const proxyFn = new Proxy(fn, {
  apply(target, that, arg) {
    …
    return target.call(that, ...arg)
  }
})

理解了Proxy,再来看下Reflect,它是一个全局对象,Proxy拦截器中的方法都能在Reflect中找到同名的方法,其实它就是提供了一个对象操作属性的默认行为。

const d = {
  a: 1
}

d.a
Reflect.get(d, 'a')

上述两种读取数据的方式是等价的,那Reflect存在的意义又是什么呢?

其实Reflect.get还可以接收第三个参数receiver,可以理解为函数调用过程中的this,以下这行事例代码读取到的值不是1而是2。

Reflect.get(d, 'a', { a: 2 })

其实Reflect还有更多方面的意义,我们只讨论这个特点,是因为它与响应式数据的实现密切相关。

2. 响应式数据的实现与Reflect的关系

在之前的代码基础上运行以下代码

const origin = {
  a: 1,
  b: 2,
  c: 3,
  get d() {
    return this.a
  }
}
const data = reactive(origin)
effect(() => {
  console.log(data.d)
})
data.a++

当data.a改变时副作用函数会响应吗?答案是不会,原因就在于这个this,当Proxy拦截到data.d的get操作时访问了this.a,这个this指向的其实是原始对象origin的a属性,而origin并不是响应式的对象。原因找到了,再来考虑如何解决问题,如果让this.a最终访问到data.a问题不就解决了嘛。Proxy拦截器可接收的参数中有一个receiver,它代表的就是当前的代理对象,再配合Reflect对象的对应方法,将reactive方法稍加改造就ok啦。

const reactive = (data) => {
  return new Proxy(data, {
    get (target, key, receiver) {
      track(target, key)
      return Reflect.get(target, key, receiver)
    },
    set (target, key, newValue, receiver) {
      const res = Reflect.set(target, key, newValue, receiver)
      trigger(target, key)
      return res
    }
  })
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值