Vue通过索引修改数组值
最近在写通过 data.slide 数组动态生成列表的时候遇到了一个问题:
1 | <div class="title-level-one" v-for="(item, index) of slide" :key="index" @click="slideClick(index)"> |
这样写没有问题,的确会根据 slide 和 slide.data 的数组去生成对应数量的列表.但是此时我想对列表做一个隐藏和显示 CSS 时, 遇到了问题:
1 | slideClick (index) { |
此时我打印 arr,发现 this.arr 的确是变了,但是 Vue 并没有响应,也就是 v-show 并没有变化.一开始我以为是 this.arr 在 fill 的时候被附了一个新对象,但是仔细一想就发现不是,在初始化的时候列表已经被隐藏了,所以肯定是因为某个原因 Vue 没有响应到this.arr[index] = !this.arr[index])
.
再仔细查了一遍官方教程以后发现了这么一段话:
由于 JavaScript 的限制,Vue 不能检测以下变动的数组:
- 当你利用索引直接设置一个项时,例如:
vm.items[indexOfItem] = newValue
- 当你修改数组的长度时,例如:
vm.items.length = newLength
举个例子:
1 | var vm = new Vue({ |
为了解决第一类问题,以下两种方式都可以实现和 vm.items[indexOfItem] = newValue
相同的效果,同时也将触发状态更新:
1 | // Vue.set |
你也可以使用 vm.$set
实例方法,该方法是全局方法 Vue.set
的一个别名:
vm.$set(vm.items, indexOfItem, newValue)
为了解决第二类问题,你可以使用 splice
:vm.items.splice(newLength)
原因是:
因为vue的底层是通过Object.defineProperty来实现数据监听更新视图的,通过索引设置数组的值不能被这个方法监听到,所以无法触发更新
所以我这里虽然修改了 this.arr 的值,但并没被 Vue 响应到.
我用数组的 splice 方法改写成如下:
1 | this.arr.splice(index, 1, !this.arr[index]) |
这样就可以了
查官方教程的时候还看到了: 对象更改检测注意事项
还是由于 JavaScript 的限制,Vue 不能检测对象属性的添加或删除:
1 | var vm = new Vue({ |
对于已经创建的实例,Vue 不能动态添加根级别的响应式属性。但是,可以使用 Vue.set(object, key, value)
方法向嵌套对象添加响应式属性。例如,对于:
1 |
|
你可以添加一个新的 age
属性到嵌套的 userProfile
对象:
Vue.set(vm.userProfile, ‘age’, 27)
你还可以使用 vm.$set
实例方法,它只是全局 Vue.set
的别名:
vm.$set(vm.userProfile, ‘age’, 27)
有时你可能需要为已有对象赋予多个新属性,比如使用 Object.assign()
或 _.extend()
。在这种情况下,你应该用两个对象的属性创建一个新的对象。所以,如果你想添加新的响应式属性,不要像这样:
1 | Object.assign(vm.userProfile, { |
你应该这样做:
1 | vm.userProfile = Object.assign({}, vm.userProfile, { |