Vue.js 中父子组件间传递表格状态数据的响应式解决方案

13次阅读

Vue.js 中父子组件间传递表格状态数据的响应式解决方案

本文讲解如何在 vue 2 中通过 `this.$set` 正确为 bootstrap table 的 `items` 数组项动态添加响应式属性(如 `state`),解决因直接赋值导致 dom 不更新的问题。

vue 2 中,响应式系统依赖于对象属性的 getter/setter 代理机制。当你对已存在的响应式对象(如 this.customItems[i])直接新增属性(例如 item.state = true),Vue 无法自动侦测该变化,因此模板中 v-if=”row.item.state” 始终读取为 undefined,即使 console.log 显示数据已写入——这是因为新属性未被纳入响应式追踪。

✅ 正确做法:使用 this.$set

必须使用 this.$set(target, key, value)(或全局 Vue.set)显式声明新属性,确保其响应式生效:

methods: {   isSingleRow(event) {     this.singleRow.push(event);     for (let i in this.customItems) {       // ❌ 错误:非响应式赋值       // this.customItems[i].state = this.singleRow[i];        // ✅ 正确:强制创建响应式属性       this.$set(this.customItems[i], 'state', this.singleRow[i]);       console.log('EHO ', i, ' state:', this.customItems[i].state);     }   } }

? 提示:this.$set 是 Vue 2 提供的官方 API,专用于向响应式对象/数组中添加新属性并触发视图更新。

? 补充说明与最佳实践

  • 为什么 created() 中 emit 不可靠?
    子组件 created 钩子执行时,父组件的 customItems 可能尚未完成初始化或异步加载,导致 singleRow 索引错位。建议改为监听 items 更新后触发逻辑,例如:

    watch: {   customItems: {     handler() {       // 确保 items 已就绪再批量初始化 state       this.customItems.forEach((item, index) => {         this.$set(item, 'state', this.singleRow[index] ?? false);       });     },     immediate: true,     deep: true   } }
  • 子组件优化建议
    当前子组件 tableRowsLength() 在 created 中调用,但未考虑 innerTableItems 是否已从 API 加载完成。应结合 v-if 或 watch 等待数据就绪:

    watch: {   innerTableItems: {     handler() {       if (this.innerTableItems.length) {         this.$emit('onitembind', this.innerTableItems.length !== 1);       }     },     immediate: true   } }
  • 模板中正确引用 slot
    注意你原代码中

                  

✅ 总结

问题 解决方案
row.item.state 在模板中为 undefined 使用 this.$set(obj, ‘state’, value) 替代直接赋值
子组件过早 emit 导致索引不匹配 改用 watch 监听数据就绪后再通信
模板结构混乱影响 slot 渲染 确保所有 v-slot 模板均置于 内部

遵循上述方式,即可实现父子组件间表格行状态(true/false)的可靠、响应式同步,确保 bootstrap Table 的条件渲染(如图标显示)实时生效。

text=ZqhQzanResources