Vue.js嵌套组件中监听isChecked变化并触发sumOfChecked方法
问题排查
你的代码主要有三个问题导致sumOfChecked没触发:
- 递归组件的事件没向上传递:子组件触发的
sum-of-checked事件未被父组件监听,深层子行的复选框变化无法传递到根组件; - 监听逻辑未覆盖深层子行:
onRowsChange仅处理了第一层行和直接子行,嵌套的子行未被递归监听,导致深层isChecked变化无法被捕获; $watch配置冗余:isChecked是基础布尔值,添加deep: true完全多余,还会增加性能开销。
分步解决方案
1. 让递归组件的事件向上冒泡
在父组件模板中,给子组件添加事件监听,将子组件的sum-of-checked事件转为自身的onCheckboxClicked触发,确保所有层级的变化都能传递到根组件:
<KreuztabelleRow v-if="row.subRows.length" :is-subitem="true" :kreuztabelle="{rows: row.subRows}" @sum-of-checked="onCheckboxClicked" />
2. 修复监听逻辑,递归处理所有嵌套子行
修改onRowsChange方法,用递归函数遍历所有层级的行,为每个isChecked添加监听,同时移除不必要的deep配置:
@Watch('rows', { immediate: true, deep: true }) onRowsChange(newRows) { const watchRow = (row) => { // 监听当前行的isChecked变化 this.$watch(() => row.isChecked, this.onCheckboxClicked, { immediate: false }); // 递归处理子行的子行 if (row.subRows?.length) { row.subRows.forEach(subRow => watchRow(subRow)); } }; newRows.forEach(row => watchRow(row)); }
3. (可选)简化复选框事件绑定
既然已经通过$watch监听isChecked变化,复选框上的@change可以直接移除,避免重复触发:
<v-checkbox v-model="row.isChecked" />
4. (最佳实践)符合Vue单向数据流规范
直接修改Prop中的row.isChecked违反了Vue单向数据流规则,建议通过事件让父组件修改数据:
- 子组件复选框改为绑定
value,用@input触发更新事件:
<v-checkbox :value="row.isChecked" @input="updateRowChecked(row, $event)" />
- 子组件添加事件发射方法:
@Emit('update-checked') updateRowChecked(row, isChecked) { return { row, isChecked }; }
- 父组件监听事件并修改数据,同时触发总和计算:
<KreuztabelleRow v-if="row.subRows.length" :is-subitem="true" :kreuztabelle="{rows: row.subRows}" @sum-of-checked="onCheckboxClicked" @update-checked="handleUpdateChecked" />
handleUpdateChecked({ row, isChecked }) { row.isChecked = isChecked; this.onCheckboxClicked(); }
更高效的实现方式
无需手动绑定大量事件和监听,直接使用计算属性即可。Vue会自动追踪数据依赖,当任何isChecked或summe变化时,计算属性会自动更新:
get totalCheckedSum() { const calculateSum = (rows) => { return rows.reduce((sum, row) => { sum += row.isChecked ? (row.summe || 0) : 0; if (row.subRows?.length) { sum += calculateSum(row.subRows); } return sum; }, 0); }; return calculateSum(this.rows); }
之后在根组件中直接使用totalCheckedSum即可,代码简洁且性能更优(计算属性自带缓存机制)。
内容的提问来源于stack exchange,提问作者maher
相关产品推荐
相关产品推荐

