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

Vue父子组件通信问题:父组件全选复选框无法同步子组件数据

解决Vue父组件修改props后子组件data不更新的问题

嘿,你遇到的这个问题其实是Vue组件响应式里的常见坑——子组件的data属性是在组件初始化时从props复制的,之后父组件修改props对应的对象属性时,子组件的data不会自动同步,因为data的初始化逻辑只在组件创建时执行一次。

咱们直接看具体的修复方案,结合你的代码来改:

方法1:用计算属性/直接使用props替代子组件的data(推荐)

你完全没必要把props.todo的属性都复制到子组件的data里,直接使用父组件传递的todo props就能自动响应变化。修改子组件代码如下:

<template>
  <div class="todo-item-container">
    <div class="todo-title-container">
      <div class="todo-id-container">
        <div id="todo-id">
          <h2>{{ todo.id }}</h2>
        </div>
      </div>
      <div id="todo-title"><h2>{{ todo.title }}</h2></div>
      <div class="todo-completed-container">
        <a href="#" class="todo-button">
          <!-- 用:checked绑定props的completed,避免直接v-model修改props -->
          <input type="checkbox" :checked="todo.completed" @change="changedCompleted">
        </a>
      </div>
      <div class="todo-delete-container">
        <a href="#" class="todo-button" @click="deletedTodo">×</a>
      </div>
    </div>
    <hr>
    <div class="todo-body-container">
      <p id="todo-body">{{ todo.body }}</p>
    </div>
  </div>
</template>

<script>
export default {
  name: 'TodoItem',
  props: {
    todo: {
      type: Object,
      required: true,
    },
    index: {
      type: Number,
      required: true,
    },
  },
  // 删掉子组件的data,直接用props的todo
  methods: {
    deletedTodo() {
      this.$emit('removeTodo', {
        index: this.index,
        todo: { ...this.todo } // 用扩展运算符复制todo对象,避免直接修改props
      })
    },
    changedCompleted(event) {
      this.$emit('changedCompleted', {
        index: this.index,
        todo: {
          ...this.todo,
          completed: event.target.checked // 更新completed状态后传给父组件
        }
      })
    },
  },
}
</script>

这样修改后,子组件直接依赖父组件的todo props,当父组件通过checkAll修改todos里的completed属性时,子组件的视图会自动更新——因为props本身是响应式的。

方法2:监听props变化更新子组件data(如果必须保留data)

如果你因为业务需求一定要保留子组件的data,可以通过watch深度监听todo props的变化,手动同步data:

<script>
export default {
  name: 'TodoItem',
  props: {
    todo: {
      type: Object,
      required: true,
    },
    index: {
      type: Number,
      required: true,
    },
  },
  data () {
    return {
      id: this.todo.id,
      title: this.todo.title,
      body: this.todo.body,
      completed: this.todo.completed,
    }
  },
  watch: {
    todo: {
      deep: true, // 因为todo是对象,需要开启深度监听
      handler(newTodo) {
        // 当父组件的todo变化时,同步更新子组件的data
        this.id = newTodo.id
        this.title = newTodo.title
        this.body = newTodo.body
        this.completed = newTodo.completed
      }
    }
  },
  methods: {
    deletedTodo() {
      this.$emit('removeTodo', {
        index: this.index,
        todo: {
          id: this.id,
          title: this.title,
          body: this.body,
          completed: this.completed,
        }
      })
    },
    changedCompleted() {
      this.$emit('changedCompleted', {
        index: this.index,
        todo: {
          id: this.id,
          title: this.title,
          body: this.body,
          completed: this.completed,
        }
      })
    },
  },
}
</script>

另外,父组件的checkAll方法还有个小问题:event没有作为参数传入,会导致报错,改一下:

checkAll(event) { // 加上event参数
  this.todos.forEach((todo) => todo.completed = event.target.checked)
}

内容的提问来源于stack exchange,提问作者sammyyy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 08:35:54