Vue数据绑定数组,改变元素时不更新view问题

问题描述

关于这个问题,Vue官方文档上说的很清楚

由于 JavaScript 的限制,Vue 不能检测以下变动的数组:

  1. 当你利用索引直接设置一个项时,例如:vm.items[indexOfItem] = newValue
  2. 当你修改数组的长度时,例如:vm.items.length = newLength

举个例子:

1
2
3
4
5
6
7
var vm = new Vue({
data: {
items: ['a', 'b', 'c']
}
})
vm.items[1] = 'x' // 不是响应性的
vm.items.length = 2 // 不是响应性的

为了解决第一类问题,以下两种方式都可以实现和 vm.items[indexOfItem] = newValue 相同的效果,同时也将触发状态更新:

1
2
// Vue.set
Vue.set(vm.items, indexOfItem, newValue)
1
2
// Array.prototype.splice
vm.items.splice(indexOfItem, 1, newValue)
1
this.items = JSON.parse(JSON.stringify(this.items))

你也可以使用 vm.$set 实例方法,该方法是全局方法 Vue.set 的一个别名:

1
vm.$set(vm.items, indexOfItem, newValue)

为了解决第二类问题,你可以使用 splice:

1
vm.items.splice(newLength)

示例说明

1
2
3
4
5
6
<body>
<div class="box">
<div v-for="a in arr">{{a}}</div>
<button @click="change">刷新国家</button>
</div>
</body>
1
2
3
4
5
6
7
8
9
10
11
12
13
var vm = new Vue({
el: '.box',
data: {
arr: ['china', 'america', 'russia', 'europe']
},
methods: {
change () {
// 点击按钮时,改变arr的最后一个元素
// 数据变了,但是view没有更新
this.arr[3] = 'hangzhou'
}
}
})

因为Vue实现双向数据绑定的机制是数据劫持,也就是在所有对象上有个Object.defineProperty()方法,通过监听set与get方法去实现,而数组没有这两个方法,所以就不会更新view。解决方案就是,需要我们主动通知Vue。

  • 解决方案1
1
2
3
4
5
6
7
methods: {
change () {
this.arr[3] = 'hangzhou'
// 在vm实例上通知
vm.$set(this.arr, 3, this.arr[3])
}
}
  • 解决方案2
1
2
3
4
5
6
7
methods: {
change () {
this.arr[3] = 'hangzhou'
// 在全局对象上通知
Vue.set(this.arr, 3, this.arr[3])
}
}
  • 解决方案3
1
2
3
4
5
6
7
methods: {
change () {
// vue本身可以监听到数组的一些方法,例如:
// push(),pop(),shift(),unshift(),splice(),sort(),reverse()
this.arr.splice(3, 1, 'hangzhou')
}
}

Powered by AppBlog.CN     浙ICP备14037229号

Copyright © 2012 - 2020 APP开发技术博客 All Rights Reserved.

访客数 : | 访问量 :