Vue中DOM未更新问题:toggleController无法禁用关联组件
Vue组件禁用功能失效排查与修复
问题描述
在Vue项目中,执行toggleController方法本应禁用对应的关联组件,该功能此前正常运行,现在突然失效。本地无代码历史版本可排查变更,尝试过$set、splice等方法修复DOM未更新问题,但均无效果。
代码分析
模板代码
<li v-for="(schema) in typeSchema" :key="schema.id" > <div style="display:inline-block; width:100%;"> <div style="display:flex; justify-content:space-between"> <span>{{ schema.title }}</span> <span v-if="schema.controller"> <MdsSwitch :checked="schema.controller.value" :label="schema.controller.title" @change="toggleController(schema, $event)" /> </span> </div> <div style="display:flex;flex-flow:column;place-items:flex-start;align-items:flex-start;margin-top:10px;"> <component :is="schema.type" v-bind="schema" :data="data" :is-disabled="schema.isDisabled" @input="updateData" /> </div> </div> </li>
方法代码
toggleController(schema, event) { if (schema.controller) { // this.typeSchema.map(x => x).in schema.controller.value = event; schema.isDisabled = !event; schema = { ...schema }; // const index = this.typeSchema.findIndex((x) => x.id === schema.id); // console.log(index); // this.$set(schema, "isDisabled", !event); // this.typeSchema.splice(index, 0, schema); } },
问题根源
- 对象引用未更新:方法中执行
schema = { ...schema }创建了新对象,但原typeSchema数组中存储的仍是旧对象的引用,Vue无法检测到数组内对象的变化。 - splice用法错误:注释中的
splice(index, 0, schema)是在索引位置插入新对象,而非替换原对象,导致数组新增元素而非更新目标对象。 - 属性检测问题:如果
isDisabled是后续新增的属性(初始schema对象中不存在),直接赋值schema.isDisabled = !event无法被Vue的响应式系统检测到。
修复方案
方案一:使用$set更新对象属性(推荐)
直接更新原对象的属性,确保Vue能检测到变化:
toggleController(schema, event) { if (schema.controller) { // 更新开关状态 this.$set(schema.controller, 'value', event); // 更新禁用状态,确保响应式 this.$set(schema, 'isDisabled', !event); } },
方案二:替换数组中的对象
找到目标对象在数组中的索引,用splice替换原对象:
toggleController(schema, event) { if (schema.controller) { schema.controller.value = event; schema.isDisabled = !event; // 找到当前schema在数组中的索引 const index = this.typeSchema.findIndex(x => x.id === schema.id); if (index !== -1) { // 替换原对象,触发数组更新 this.typeSchema.splice(index, 1, { ...schema }); } } },
额外注意事项
- 确保初始的
typeSchema数组中,每个schema对象都包含isDisabled属性(哪怕初始值为false),这样Vue在初始化时就能将其纳入响应式系统。 - 避免直接修改对象后重新赋值却不更新数组的操作,必须保证数组内的对象引用发生变化或属性被响应式更新。
内容的提问来源于stack exchange,提问作者Krishna Pahlajani
相关产品推荐
相关产品推荐

