You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 01:52:06