Vue.js 异步修改数组数据后template模板未更新问题咨询
问题原因
这个问题本质是Vue2响应式系统的数组操作限制,加上两种代码执行时机的差异导致的:
- Vue2基于
Object.defineProperty实现响应式,无法直接监听到数组索引赋值、数组长度修改这两类操作,只有被重写的7个数组变异方法(push/pop/shift/unshift/splice/sort/reverse)、或者直接替换整个数组引用的操作,才会触发视图更新。 - 同步代码可以正常运行的原因:created钩子执行时,组件还未完成首次模板渲染,你同步给
items数组赋值的内容,会被纳入首次渲染的响应式初始化流程,所以模板能正常读取到数据渲染。 - 异步代码无法触发更新的原因:setTimeout回调执行时,组件已经完成了首次渲染,此时通过
this.items[index] = xxx的方式修改数组,操作没有被响应式系统捕获,所以不会触发模板重新渲染。
解决方案
你可以选择以下任意一种方式修改代码:
- 使用Vue提供的
$set方法主动通知响应式更新:
for (let index = 0; index < this.predefinedItems.length; index++) { const newItem = { ...this.predefinedItems[index], i: index, x: 1, y: 1, w: 12, h: 8, accent: 'info' } this.$set(this.items, index, newItem) }
- 使用数组splice方法修改内容:
for (let index = 0; index < this.predefinedItems.length; index++) { const newItem = { ...this.predefinedItems[index], i: index, x: 1, y: 1, w: 12, h: 8, accent: 'info' } this.items.splice(index, 1, newItem) }
- 先构造完整的新数组,再整体替换原数组的引用(最通用的方案):
const tempItems = [...this.items] for (let index = 0; index < this.predefinedItems.length; index++) { tempItems[index] = { ...this.predefinedItems[index], i: index, x: 1, y: 1, w: 12, h: 8, accent: 'info' } } this.items = tempItems
内容的提问来源于stack exchange,提问作者Andreas Hunter
相关产品推荐
相关产品推荐

