Vue3.0 里为什么要用 Proxy API 替代 defineProperty API

476 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

Vue3.0 里为什么要用 Proxy API 替代 defineProperty API

Vue3.0 里用 Proxy API主要是为了做响应式优化

a. defineProperty API 的局限性最大原因是它只能针对单例属性做监听。Vue2.x 中的响应式实现正是基于 defineProperty 中的 descriptor,对data 中的属性做了遍历 + 递归,为每个属性设置了 getter、setter。 这也就是为什么 Vue 只能对 data 中预定义过的属性做出响应的原因,在Vue 中使用下标的方式直接修改属性的值或者添加一个预先不存在的对象属性是无法做到setter 监听的,这是 defineProperty 的局限性。

b. Proxy API 的监听是针对一个对象的,那么对这个对象的所有操作会进入监听操作,这就完全可以代理所有属性,将会带来很大的性能提升和更优的代码。Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。

c. 响应式是惰性的 在 Vue.js 2.x 中,对于一个深层属性嵌套的对象,要劫持它内部深层次的变化,就需要递归遍历这个对象,执行 Object.defineProperty()API把每一层对象数据都变成响应式的,这无疑会有很大的性能消耗。 而在 Vue.js 3.0 中,使用 Proxy API 并不能监听到对象内部深层次的属性变化,因此它的处理方式是在 getter 中去递归响应式,这样做的好处是真正访问到的内部属性才会变成响应式,简单的可以说是按需实现响应式,减少性能消耗

Proxy的基础用法如下代码所示:

let datas = {
   num:0 
}
let proxy = new Proxy(datas,{
    get(target,property){
	return target(property]
    }
    set(target property,value){
	target[property]+=value
    }
})