vue中Proxy 相比于defineProperty 的优势

文章类型:Vue

发布者:hp

发布时间:2023-03-17

vue2中采用defineProperty,而vue3中采用Proxy 方式实现数据的响应式,那么两者的区别和优势是什么,今天进行一下整理

一:Object.defineProperty()

A:主要问题

1:不能监听数组的变化,无法监听数组下标的变化,导致采用下标方式添加的数据不能实时响应

2:必须遍历对象的每个属性,主要是劫持对象的属性,如果属性是对象,那么必须深层次遍历嵌套的对象

3:对数组支持不友好,采取的重写7个数组方法方式,push、pop、unshift、splice

B:优势

兼容性好,支持 IE9

C:属性

value:123=> 初始值

writable:true,=>该属性是否可写入

enumerable:true,=> 该属性是否可被遍历得到(for...in, Object.keys等)

configurable:true=> 该属性是否可被删除,且除writable外的其他描述符是否可被修改

Object.defineProperty(obj, prop, descriptor)

// obj 要定义属性的对象
// prop 要定义或修改的属性的名称
// descriptor 要定义或修改的属性描述符

Object.defineProperty(obj,"name",{
value:"poetry", // 初始值
writable:true, // 该属性是否可写入
enumerable:true, // 该属性是否可被遍历得到(for...in, Object.keys等)
configurable:true, // 定该属性是否可被删除,且除writable外的其他描述符是否可被修改
get: function() {},
set: function(newVal) {}
})

二:Proxy

A:优势

1:主要是针对整个对象,而不是针对对象的某个属性,所以不需要对属性进行深层次遍历

2:支持数组,不需要对数组的方法进行重载,减少代码量、维护成本

3:Proxy的第二个参数可以有 13 种拦截方法:get、set、has、deleteProperty等

4:返回的是一个新对象,可以只操作新的对象达到目的,而Object.defineProperty只能遍历对象属性直接修改

5:Proxy作为新标准会得到更好的性能优化和支持

B:问题

Proxy 的存在浏览器兼容性问题,而且无法用 polyfill 来兼容

C:属性

target是被代理的对象

handlder是声明了各类代理操作的对象,最终返回一个代理对象

newProxy(target,handle);

三:vue3怎么解决代理对象只能监听一层

1:判断当前Reflect.get的返回值是否为Object,如果是则再通过reactive方法做代理

2:监测数组的时候可能触发多次get/set,可以判断key是否为当前被代理对象target自身属性、判断旧值与新值是否相等,只有满足以上两个条件之一,才有可能执行trigger