写在前面:
由于vue本身的缺陷(也可以说是js本身的缺陷),在vue中,特定的数值的改变可能并不会引起数值更新,即使在调试工具中已经显示数据更新了。
于是,你焦头烂额,先是打开调试工具,查看数据更新,然后对自己的源码一通乱改,解决无果,于是打开百度、谷歌各大搜索引擎搜索一通,最后发现,各个回答水平参差不齐,运气好,你可能10分钟解决问题,运气不好,可能就是n个10分钟。所以为了解决这样的问题,我决定写下这篇文章,帮助有困难的小伙伴解决问题。
part1.为什么视图会没有变化?
VUE的视图更新是通过拦截器实现的,但这其中并不包括对数组类型数据的下标引用,即
array[0]=8;
这种形式的数据变化不会被vue检测到。
but,vue在原生方法
Array.push()
Array.pop()
Array.shift()
Array.unshift()
Array.splice(i,n,arr)
Array.sort()
Array.reverse()
设置有拦截器,所以如果可能,请尽量用这些方法来改变数组数据而不是下标直接索引。
除此之外,在Obeject类型的对象中:
object['anyProperty']=8
是可以被vue拦截检测的。
如果想完全了解这其中的过程移步:
Vue源码系列-Vue中文社区
你可能会疑惑,为什么vue不对数组的下标索引数据设置拦截器?原因很简单设置不了。
demo:
const obj = {
data: { name: '李华', age: null },
set age(value) {
console.log('通过代理设置');
this.data.age = value;
},
get age() {
console.log('通过代理获得');
return `年龄是: ${this.data.age}`;
}
};
obj.age = 99; //通过代理设置
console.log(obj) //{ name: '李华', age: 99 }
对象尚且可以用js原生的能力直接设置拦截器,但数组却不行,因为数组没办法设置set property,get property。所以这既是vue的缺陷,也是js的缺陷。
part2.解决方案
1.使用全局API
<div id="app">
<p>{{array}}</p>
<button @click="changeData">change_array</button>
<button @click="deleteData">delete_array</button>
</div>
let app = new Vue({
el: '#app',
data: {
array: [0, 1, 2, 3],
},
methods: {
changeData: function () {
this.$set(this.array,0,8)
},
deleteData:function(){
this.$delete(this.array,0)
}
}
})
2.让VUE强制检测一次数组
changeData: function () {
this.array[0] = 8;
this.array.push();
},
所以你完全可以把这两行语句封装成一个函数
function arrChange(array,index,newData){
this.array[index] = newData;
this.array.push();
}
//在vue使用
changeData: function () {
arrChange.call(this,this.array,0,8)
},
是不是很眼熟?
删除同理,不赘述
3.使用vuex
移步:vuex官方文档
这里不推荐使用这种方法,因为相比于上面所述的方法,过于冗余。
网友评论