You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Vue.js中v-for修改数组元素为何不触发重新渲染?

为什么Vue中v-for修改数组索引元素不触发响应?

这个问题是Vue2响应式系统里的一个常见“坑”,我来给你讲明白背后的原因和解决办法~

为什么直接修改索引没反应?

Vue2的响应式是基于Object.defineProperty实现的,这个API可以监听对象属性的读取和修改,但对数组来说,它没办法拦截两种操作

  • 直接通过索引修改数组元素,比如this.test[3] = 3
  • 直接修改数组的length属性,比如this.test.length = 0

当你执行this.test[3] = 3时,Vue的响应式系统完全没察觉到数据发生了变化,自然不会触发视图的重新渲染。

为什么push之后就生效了?

为了解决数组响应式的问题,Vue2对数组的7个原生方法做了“包装”,这些方法包括:pushpopshiftunshiftsplicesortreverse

被包装后的方法,在执行原生数组操作的同时,会主动触发Vue的响应式更新逻辑,通知视图重新渲染。所以当你先修改索引再调用push时,push触发了更新,之前修改的元素也就跟着显示出来了。

正确的解决办法

如果你想直接修改数组索引对应的元素并触发响应,有几种靠谱的方式:

1. 使用this.$set(或全局的Vue.set

这是Vue官方推荐的方法,它会主动把新元素加入响应式系统,同时触发视图更新:

changeVar2: function() {
  this.$set(this.test, 3, 3);
}

2. 使用数组的splice方法

splice是被Vue包装过的方法,执行时会触发响应式更新,你可以用它来替换指定索引的元素:

changeVar2: function() {
  // 参数含义:从索引3的位置,替换1个元素,新元素是3
  this.test.splice(3, 1, 3);
}

3. 替换整个数组(适合场景化需求)

你可以通过扩展运算符或者其他方式生成一个新数组,替换原数组,因为Vue可以监听数组的替换操作:

changeVar2: function() {
  this.test = [...this.test, , , 3];
}

补充:Vue3的情况

如果是用Vue3的话,这个问题就不存在了,因为Vue3用Proxy代替了Object.defineProperty,Proxy可以直接拦截数组的索引修改、长度变化等操作,原生的数组操作都能触发响应式更新。

内容的提问来源于stack exchange,提问作者Ilya Egorov

火山引擎 最新活动