vue2 的 Object.defineProperty 为什么不在 get 中递归?为什么 vue3 Proxy 中可以?
这是 vue2
采取数据监听的方式
function defineReactive(target, key, value) { //深度监听
observer(value)
Object.defineProperty(target, key, {
get() {
return value
}
})
}
这是 vue3
采取数据监听的方式,在 get
中才去监听
// reactive 中有 Proxy 操作const handler = {
get: function (obj, prop) {
const res = Reflect.get(obj, prop)
if (typeof res === 'object') {
return reactive(res, handler)
}
return res
}
}
const p = reactive(bigData, handler)
vue3
为了避免多次 get
导致的多次递归,在 reactive
中会判断是否已经被代理过,如果是会直接返回对象
那 vue2
为什么不这么做,反而是直接在代理属性时就选择数据监听,如果选择在 get
中,当数据被访问时再递归子对象/数组,这样不就不会有递归的性能问题了吗?
回答:
可以看下我的这篇文章
反向操作,用 Object.defineProperty 重写 @vue/reactivity
虽然实际上没多大应用场景,但是可以看看怎么用defineProperty
实现vue3的
回答:
可能是因为Object.defineProperty是针对对象单个属性进行监听的,所以要放在get中的话,需要一个一个遍历,性能影响是一方面,还有一方面是vue2中数组是不监听的,如果是一个数组对象,数组不监听,走不到get,还怎么监听里面的对象。
而proxy是针对对象本身去监听的,无论数组还是对象都可以监听,运行时监听可以减少其他无用数据监听带来的消耗
回答:
所以,综合楼上所说,vue3
判断对象是否被代理过是使用了WeakMap
,这是一个ES6
的语法,在当时的vue2
是不可能使用的,当时来说对于WeakMap
又没有什么好的替代品,所以vue2
没有采用这样的判断机制。不知道我说的对否
以上是 vue2 的 Object.defineProperty 为什么不在 get 中递归?为什么 vue3 Proxy 中可以? 的全部内容, 来源链接: utcz.com/p/937357.html