Vuetify CRUD表格编辑对话框异常:修改本地对象同步更新表格
Vuetify CRUD表格编辑对话框同步修改原数据问题解决
我基于Vuetify开发一个数据操作的简易CRUD表格,已用模拟数据复现问题,目前实现了FoodTable、EditDialog和Delete三个组件。遇到的异常:尝试传递对象副本给EditDialog组件,但修改对话框中的值时,DataTable里的对应值也会同步更新。
相关代码
FoodTable.vue
<template> <div> <EditDialog :IsOpen="editIsOpen" :EditObject="editObject" @edit-closed="editClosed" /> <v-data-table :headers="headers" :items="items"> <template v-slot:item.actions="{ item }"> <v-icon>mdi-delete</v-icon> <v-icon @click="openEdit(item)">mdi-pencil</v-icon> </template> </v-data-table> </div> </template> <script> import EditDialog from '../components/EditDialog.vue'; export default { name: 'FoodTable', components: { EditDialog, }, data() { return { headers: [ { text: 'Dessert (100g serving)', align: 'start', sortable: false, value: 'name', }, { text: 'Calories', value: 'calories' }, { text: 'Fat (g)', value: 'fat' }, { text: 'Carbs (g)', value: 'carbs' }, { text: 'Protein (g)', value: 'protein' }, { text: 'Actions', value: 'actions', sortable: false }, ], items: [ { name: 'Frozen Yogurt', calories: 159, fat: 6.0, carbs: 24, protein: 4.0, }, { name: 'Ice cream sandwich', calories: 237, fat: 9.0, carbs: 37, protein: 4.3, }, ], // edit editIsOpen: false, editObject: {}, // delete } }, methods: { openEdit(item) { this.editIsOpen = true; this.editObject = item; }, editClosed() { this.editIsOpen = false; this.editObject = {}; } } } </script>
EditDialog.vue
<template> <v-dialog v-model="isOpen" persistent> <v-card> <v-card-title>Edit</v-card-title> <v-card-text> <v-text-field v-model="editObject.calories"></v-text-field> </v-card-text> <v-card-actions> <v-spacer></v-spacer> <v-btn @click="cancelEdit">Cancel</v-btn> <v-btn @click="confirmEdit">Confirm</v-btn> </v-card-actions> </v-card> </v-dialog> </template> <script> export default { name: 'EditDialog', props: { IsOpen: Boolean, EditObject: Object, }, data() { return { isOpen: this.IsOpen, editObject: this.EditObject, } }, methods: { cancelEdit() { this.$emit('edit-closed'); }, confirmEdit() { this.$emit('edit-closed'); } }, watch: { IsOpen() { this.isOpen = this.IsOpen; }, EditObject(newEditObject){ this.editObject = newEditObject; } } } </script>
期望流程
- 点击编辑图标触发
@click事件,调用openEdit方法并传入当前item; - 设置
editIsOpen为true,并将editObject赋值为传入的item; - 将这些值作为props传递给EditDialog组件;
- EditDialog组件监听props变化,将本地变量
isOpen和editObject设置为props的值; - EditDialog中的文本框绑定本地
editObject的属性,仅修改本地对象; - 点击提交后,组件向上传递新对象并更新表格数据(暂未实现)。
问题点
修改对话框中的值时,不仅本地editObject被修改,表格中对应的变量也被同步修改。
原因分析
JavaScript中对象是按引用传递的:
- 父组件
openEdit方法里this.editObject = item只是把item的引用赋值给了editObject; - 子组件把props的
EditObject赋值给本地editObject时,同样是传递引用; - 所以修改子组件中
editObject的属性,本质上是直接修改原数组items中对应对象的属性,导致表格数据同步变化。
解决方法
在子组件接收EditObject时,创建对象的副本(断开引用),可以通过手动复制属性、Object.assign或者扩展运算符...实现。这里修改EditDialog的watch逻辑:
watch: { IsOpen() { this.isOpen = this.IsOpen; // 创建对象副本,断开与原对象的引用 let editObject = { name: this.EditObject.name, calories: this.EditObject.calories, fat: this.EditObject.fat, carbs: this.EditObject.carbs, protein: this.EditObject.protein, } this.editObject = editObject; }, // 也可以优化EditObject的watch,直接创建副本 EditObject(newEditObject){ this.editObject = {...newEditObject}; // 扩展运算符更简洁 } }
这样修改对话框中的值时,只会修改本地副本,不会影响原表格数据,点击确认后再将副本数据传递给父组件更新原数组即可。
内容的提问来源于stack exchange,提问作者sdman02
相关产品推荐
相关产品推荐

