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

问题描述

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

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

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

举个例子:

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

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

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

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

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

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

vm.items.splice(newLength)

示例说明

<body>
  <div class="box">
    <div v-for="a in arr">{{a}}</div>
    <button @click="change">刷新国家</button>
  </div>
</body>
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
methods: {
  change () {
    this.arr[3] = 'hangzhou'
    // 在vm实例上通知
    vm.$set(this.arr, 3, this.arr[3])
  }
}
  • 解决方案2
methods: {
  change () {
    this.arr[3] = 'hangzhou'
    // 在全局对象上通知
    Vue.set(this.arr, 3, this.arr[3])
  }
}
  • 解决方案3
methods: {
  change () {
    // vue本身可以监听到数组的一些方法,例如:
    // push(),pop(),shift(),unshift(),splice(),sort(),reverse()
    this.arr.splice(3, 1, 'hangzhou')
  }
}
上一篇 Vue过滤器
下一篇 vue-resource HTTP
目录
文章列表
1 Dagger2使用入门
Dagger2使用入门
2
Spring Security OAuth2 JWT 认证服务器配置
Spring Security OAuth2 JWT 认证服务器配置
3
Spring Cloud @RefreshScope和@EventListener实现Nacos配置更新监听
Spring Cloud @RefreshScope和@EventListener实现Nacos配置更新监听
4
numpy.linalg学习
numpy.linalg学习
5
微信公众号支付WeixinJSBridge与JS-SDK
微信公众号支付WeixinJSBridge与JS-SDK
最新评论
一位WordPress评论者
一位WordPress评论者
2月12日
您好,这是一条评论。若需要审核、编辑或删除评论,请访问仪表盘的评论界面。评论者头像来自 Gravatar。