为什么Vue3.0使用Proxy实现数据监听(defineProperty表示不背这个锅)

2020-06-12 20:45:47易采站长站整理

导 读

vue3.0中,响应式数据部分弃用了

Object.defineProperty
,使用
Proxy
来代替它。本文将主要通过以下方面来分析为什么vue选择弃用
Object.defineProperty

Object.defineProperty
真的无法监测数组下标的变化吗?
分析vue2.x中对数组
Observe
部分源码
对比
Object.defineProperty
Proxy

一、无法监控到数组下标的变化?

在一些技术博客上看到过这样一种说法,认为

Object.defineProperty
有一个缺陷是无法监听数组变化:

无法监控到数组下标的变化,导致直接通过数组的下标给数组设置值,不能实时响应。所以vue才设置了7个变异数组(

push
pop
shift
unshift
splice
sort
reverse
)的
hack
方法来解决问题。

Object.defineProperty
的第一个缺陷,无法监听数组变化。 然而Vue的文档提到了Vue是可以检测到数组变化的,但是只有以下八种方法,
vm.items[indexOfItem] = newValue
这种是无法检测的。

这种说法是有问题的,事实上,

Object.defineProperty
本身是可以监控到数组下标的变化的,只是在 Vue 的实现中,从性能/体验的性价比考虑,放弃了这个特性。

下面我们通过一个例子来为

Object.defineProperty
正名:


function defineReactive(data, key, value) {
Object.defineProperty(data, key, {
enumerable: true,
configurable: true,
get: function defineGet() {
console.log(`get key: ${key} value: ${value}`)
return value
},
set: function defineSet(newVal) {
console.log(`set key: ${key} value: ${newVal}`)
value = newVal
}
})
}

function observe(data) {
Object.keys(data).forEach(function(key) {
defineReactive(data, key, data[key])
})
}

let arr = [1, 2, 3]observe(arr)

上面代码对数组arr的每个属性通过

Object.defineProperty
进行劫持,下面我们对数组arr进行操作,看看哪些行为会触发数组的