Vue3中通过Props初始化复选框选中状态问题求助
问题根源
- 复选框绑定冲突:同时使用
:checked和v-model,v-model会完全接管复选框的选中状态,导致:checked="element.finish"的设置被覆盖。 - props直接修改违反单向数据流:
tasksList是父组件传入的props,直接修改其中的task.finish不会触发视图更新,且不符合Vue的设计规范。 - 状态更新逻辑错误:
updateTasksList方法中依赖finishedTask数组判断状态,逻辑与实际需求不匹配。
修复步骤
1. 清理复选框冗余绑定
删除v-model="finishedTask"和:value="element.id",只保留:checked="element.finish"来关联任务的完成状态:
<input @change="updateTasksList(element, $event)" type="checkbox" :checked="element.finish" >
2. 把props转为本地可修改数据
Vue禁止直接修改props,所以需要将父组件传入的tasksList复制到组件本地的data中,并监听props变化同步更新:
data() { return { drag: false, localTasksList: [...this.tasksList] // 复制props到本地 } }, watch: { tasksList(newList) { this.localTasksList = [...newList] // 父组件更新时同步本地数据 } }
同时把draggable的v-model改为本地数据:
<draggable v-model="localTasksList" tag="div" item-key="id" :move="checkMove" ghost-class="ghost" chosen-class="chosen" >
3. 简化状态更新逻辑
直接根据复选框的选中状态设置任务的finish属性,不需要依赖额外数组:
async updateTasksList(task, event) { task.finish = event.target.checked; // 直接绑定复选框状态 await this.updateTask(task); // 通知父组件更新列表(可选,配合父组件的.sync修饰符使用) this.$emit('update:tasksList', [...this.localTasksList]); }
4. 父组件同步更新(可选)
如果需要父组件同步更新任务列表,在父组件使用组件时添加.sync修饰符:
<task-list :tasks-list.sync="parentTasksList" :list-id="xxx" :show-task-list="xxx" />
修复后完整代码
模板部分
<template > <div :class="[ showTaskList === true ? '' : 'hidden' ] + ' mt-4 task-list list weekList flex flex-col p-6 max-w-sm mx-auto bg-gray rounded-xl shadow-lg'" > <div class="flex flex-row gap-4"> Liste des taches ({{listId}}) <button @click="displayForm(listId)" class="px-2 rounded bg-blue text-white text-sm uppercase right">+</button> <hr class="text-gray1 mb-4"> </div> <draggable v-model="localTasksList" tag="div" item-key="id" :move="checkMove" ghost-class="ghost" chosen-class="chosen" > <template #item="{element, index}"> <div class="container flex flex-row"> <div class=""> <div class="title font-bold">{{ element.title }}</div> <div class="date text-sm text-left text-gray1">Terminé <input @change="updateTasksList(element, $event)" type="checkbox" :checked="element.finish" > </div>{{element.id}} - {{element.finish}} </div> <div class="ml-auto font-bold text-right"> <button v-if="element.id" @click="$store.dispatch('removeTask', element.id)" > Supprimer </button> </div> </div> </template> </draggable> </div> </template>
脚本部分
import Draggable from 'vuedraggable'; import axios from 'axios'; axios.defaults.baseURL = 'http://localhost:3000'; export default { name: 'taskList', props: ['tasksList','listId', 'showTaskList'], components: { Draggable, }, data() { return { drag: false, localTasksList: [...this.tasksList], } }, watch: { tasksList(newList) { this.localTasksList = [...newList]; } }, methods: { displayForm() { this.$emit('displayForm', this.listId); }, checkMove(e) { console.log("checkMove"); console.log(e.draggedContext.element.position); }, async updateTasksList(task, event) { task.finish = event.target.checked; await this.updateTask(task); this.$emit('update:tasksList', [...this.localTasksList]); }, async updateTask(task) { try { const message = await axios.patch(`/task/${task.id}`, task); if (!message) { this.$store.dispatch('setError', 'Impossible de créer la tache'); } this.message = 'Tache update'; } catch (error) { this.$store.dispatch('setError', error); } } }, computed: { error() { return this.$store.state.error; }, }, }
内容的提问来源于stack exchange,提问作者florian_drupal
相关产品推荐
相关产品推荐

