在Vue.js状态数组元素上动态新增属性是否会破坏响应式?
问题根因
该问题是Vue 2.x版本的响应式系统限制导致:Vue 2基于Object.defineProperty实现响应式,仅能劫持初始化时就在data中声明的属性,运行时直接给已有对象动态追加未声明的属性,不会被响应式系统追踪。
你当前的两个操作均触发了该限制:
- 直接给sentence对象新增
words属性 - 直接给sentence下的grade对象新增
selected属性
修复方案
方案1:使用Vue内置的$set方法添加属性
$set是Vue专门用来给响应式对象新增可追踪属性的API,修改你的mounted逻辑即可:
mounted(){ this.sentences = this.sentences.map((sentence, index) => { let words = []; sentence.text.split(' ').forEach((word, i) => { words.push({ text: word, selected: false }) }); this.$set(sentence, 'words', words) this.$set(sentence.grade, 'selected', false) return sentence; }) }
方案2(更推荐):返回全新对象替换原有对象
不需要修改原有对象,直接在map中返回整合了新属性的全新对象,赋值给this.sentences时会整体做响应式处理,性能更稳定:
mounted(){ this.sentences = this.sentences.map((sentence, index) => { const words = sentence.text.split(' ').map(word => ({ text: word, selected: false })) return { ...sentence, words, grade: { ...sentence.grade, selected: false } } }) }
注:如果你使用的是Vue 3版本,不存在该问题,Vue 3基于Proxy代理整个对象,动态追加的属性也能被响应式追踪。
内容的提问来源于stack exchange,提问作者Onyx
相关产品推荐
相关产品推荐

