Vue不能观察到数组length的变化
由于JavaScript的限制,Vue不能检测以下变动的数组:当你利用索引直接设置一个项时,例如:vm.items[indexOfItem]=newValue当你修改数组的长度时,例如:vm.items.length=newLength
因为vue的响应式是通过Object.defineProperty来实现的,但是数组的length属性是不能添加getter和setter,所有无法通过观察length来判断。
为什么Vue不能观察到数组length的变化
如下代码,虽然看起来数组的length是10,但是forin的时候只能遍历出0,1,2,导致了只有前三个索引被加上了getter和setter
vara=[0,1,2]
a.length=10
//只是显示的给length赋值,索引3-9的对应的value也会赋值undefined
//但是索引3-9的key都是没有值的
//我们可以用for-in打印,只会打印0,1,2
for(varkeyina){
console.log(key)//0,1,2
}
那么vue提供了一些解决方法
使用内置的Vue.$set
让数组显式的进行某个索引的观察Vue.set(array,indexOfItem,newValue)
实际上是调用了
Object.defineProperty(array,indexOfItem,{
enumerable:true,
configurable:true,
get(){},
set(newVal){}
})
这样可以手动指定需要观察的key,那么就可以达到预期的效果。
重写了push,pop,shift,unshift,splice,sort,reverse方法
Vue源码
constarrayProto=Array.prototype
exportconstarrayMethods=Object.create(arrayProto)
/**
*Interceptmutatingmethodsandemitevents
*/
;[
'push',
'pop',
'shift',
'unshift',
'splice',
'sort',
'reverse'
]
.forEach(function(method){
//cacheoriginalmethod
constoriginal=arrayProto[method]
def(arrayMethods,method,functionmutator(...args){
constresult=original.apply(this,args)
constob=this.__ob__
letinserted
switch(method){
case'push':
case'unshift':
inserted=args
break
case'splice':
inserted=args.slice(2)
break
}
if(inserted)ob.observeArray(inserted)
//notifychange
ob.dep.notify()
returnresult
})
})
这些是在Array.__proto__上进行了方法重写或者添加
并且对添加属性的方法如push,unshift,splice所添加进来的新属性进行手动观察,源码为
if(inserted)ob.observeArray(inserted)
对以上方法进行了手动的进行消息触发
ob.dep.notify()
结论
vue对数组的length直接改变无法直接进行观察,提供了vue.$set进行显式观察,并且重写了push,pop,shift,unshift,splice,sort,reverse方法来进行隐式观察。
以上所述是小编给大家介绍的Vue不能观察到数组length的变化,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对毛票票网站的支持!