vue2不能检测哪些变化?
1.数组元素的增改
2.对象的增删
data(){
return{
arr:[1,2,3];
obj:{a:1,b:2,c:3};
}
}
//this.arr[3] = 4;//数据更改为[1,2,3,4],view视图并未更改
//this.arr[0] = 0;//数据更改为[0,2,3],view视图并未更改
//this.obj.d = 4; //数据更改为{a:1,b:2,c:3,d:4},view视图并未更改
//delete this.obj.a; //数据更改为{b:2,c:3},view视图并未更改
vue2采用Object.defineProperty()来劫持数据,Object.defineProperty()本身是能够检测到这些变化的,但是由于性能问题而没有采用;
在vue2源码里面为什么要重写数组方法,出于什么性能问题呢?
以下是对vue2劫持数据的模拟
function defineReactive(obj, key, value) {
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get() {
console.log(`获取的key:${key},值:${value}`);
return value;
},
set(newValue) {
value = newValue;
console.log(`设置的key:${key},值:${value}`);
}
})
}
function observe(data) {
const keys = Object.keys(data)
for (let i = 0; i < keys.length; i++) {
const key = keys[i]
defineReactive(data, key, data[key])
}
}
var arrlist = ["张", "王", "李"]
observe(arrlist)
当我执行以下操作
//arrlist[0] = "徐";
控制台打印--设置的key:0,值:徐
//arrlist.push("赵");
没有触发get set
//arrlist.unshift("熊");
控制台打印
获取的key:2,值:李
获取的key:1,值:王
设置的key:2,值:王
获取的key:0,值:张
设置的key:1,值:张
设置的key:0,值:熊
总结:
Object.defineProperty只能检测对象初始时,已定义的key;对于数组,设置已监听数据的下标时,才会触发。数组push 一定不会触发get set,unshift shift pop可能会触发,比如不断进行pop操作数组为[],就不会再次触发,所以是可能;并不是Object.defineProperty监听不到数组的变更,而是对数组的每一次操作都可能会影响其他值索引的变更(对象则不会影响其他key),在多数情况下,需要重新遍历数组,重新检测,例如unshift操作,当数据特别多的时候非常浪费性能。