由于 JavaScript 的限制, Vue 不能检测以下变动的数组:
- 当你直接设置一个项的索引时,例如:
vm.items[indexOfItem] = newValue
- 当你修改数组的长度时,例如:
vm.items.length = newLength
为了避免第一种情况,以下两种方式将达到像 vm.items[indexOfItem] = newValue 的效果, 同时也将触发状态更新:
Vue.set(example1.items, indexOfItem, newValue)
this.items.splice(indexOfItem, 1, newValue)
看例子:
<!-- html 部分 -->
<div id="app">
<ul>
<li v-for="item in statu">{{item}}</li>
<button @click="addItem">添加</button>
<button @click="viewItem">打印</button>
</ul>
</div>
// js 部分
new Vue({
el: '#app',
data: {
statu: ['第一个', '第二个', '第三个']
},
methods: {
viewItem() {
console.log(this.statu)
},
addItem() {
this.statu[1] = "我是新添加的"
}
},
})
上面代码直接设置一个项的值, 结果如下:
点击添加按钮,页面上的元素不会发生变化,但是点击打印发现数组确实被改变了,之所以页面没有渲染是因为直接设置下标这种方式不会被 vue
检测到。
现在用第一种方式去改变数组。
addItem() {
this.$set(this.statu, 1, "我是新添加的")
}
使用这种方式点击添加按钮之后页面如下:
现在使用第二种方式去改变数组。
addItem() {
this.statu.splice(1, 1, "我是新添加的")
}
使用这种方式点击添加按钮之后页面如下:
可以看到上面这两种方式都会被 vue 检测到。
避免第二种情况,使用 splice :
this.items.splice(this.items.length = newLength)
addItem() {
this.statu.splice(this.statu.length = 6)
}
通过这种方式改变数组长度,vue 可以检测到,而如果直接写 this.statu.length = 6, vue 是不会检测到的,页面也不会更新。