在vue中 列表渲染算是最常用的功能之一,但是在列表渲染中有个一比较明显的问题:
在列表渲染中,经常发生数据变化,但是视图层并未改变的状况,根据官方:
由于 JavaScript 的限制,Vue 不能检测以下变动的数组:
- 当你利用索引直接设置一个项时,例如:
vm.items[indexOfItem] = newValue
- 当你修改数组的长度时,例如:
vm.items.length = newLength
还有一个注意点是 :不论是当前循环的数组数据,还是在循环列表中用到的数组数据,都不能在视图同步响应这两种数据改变。
例如:
<template v-for="(item, index) in receiveData"> <a :class="list[index]?'visiteColor':''" :key="item.id" @click="linkColor(index)"> <p class="dateFont">{{item.date}}</p> <p>{{list}}</p> </a> </template>
这时候,数组receiveData 和数据 list 是都不能通过 索引改变视图层的,所以就会出现 数据改变,但是视图不变的情况
解决方法官方也给了:
// Vue.set
Vue.set(vm.items, indexOfItem, newValue)
// Array.prototype.splice
vm.items.splice(indexOfItem, 1, newValue)
你也可以使用 vm.$set
实例方法,该方法是全局方法 Vue.set
的一个别名:
vm.$set(vm.items, indexOfItem, newValue)
为了解决第二类问题,你可以使用 splice
:改变数组的长度
vm.items.splice(newLength)
我在组件中写的例子:
export default { data () { return { list: [true], receiveData: [ { date: '2018-06-10' }, { date: '2018-06-10' } ] }; }, methods: { linkColor (index) { for (let i = 0; i < this.list.length; i++) { if (i !== index) { // 循环中的数组赋值 this.$set(this.list, i, false); this.$set(this.list, index, true); } } console.log(this.list); } } };