避免直接改变道具 - Datatable VueJS
Posted
技术标签:
【中文标题】避免直接改变道具 - Datatable VueJS【英文标题】:Avoid mutating a prop directly - Datatable VueJS 【发布时间】:2020-06-23 17:16:09 【问题描述】:我是 Vue JS 的新手,我遇到了这个问题我尝试通过将父道具传递给孩子来制作数据表
我收到此错误
[Vue 警告]:避免直接改变 prop,因为每当父组件重新渲染时,该值都会被覆盖。相反,使用基于道具值的数据或计算属性。正在变异的道具:“editedItem”
这是我的代码
这是我的主页:
<template >
<v-container >
<v-col>
<Datatables
:headers="this.headers"
:items="items"
:editedItem="this.editedItem"
:defaultItem="defaultItem"
sort-by="calories"
class="elevation-1" />
</v-col>
<v-spacer></v-spacer>
<br>
<v-col>
</v-col>
</v-container >
</template>
<script>
import Datatables from '../../components/Datatable/CrudDatatable'
export default
components:
Datatables
,
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: 'action', sortable: false ,
],
items: [],
editedItem:
name: '',
calories: 0,
fat: 0,
carbs: 0,
protein: 0,
,
defaultItem:
name: '',
calories: 0,
fat: 0,
carbs: 0,
protein: 0,
,
,
created ()
this.initialize()
,
methods:
initialize ()
this.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,
,
]
,
,
</script>
<style>
</style>
这是我的组件:
<template>
<v-data-table :headers="headers" :items="items" sort-by="calories" class="elevation-1">
<template v-slot:top>
<v-toolbar flat color="white">
<v-toolbar-title>My CRUD</v-toolbar-title>
<v-divider class="mx-4" inset vertical></v-divider>
<v-spacer></v-spacer>
<v-dialog v-model="dialog" max->
<template v-slot:activator=" on ">
<v-btn color="primary" dark class="mb-2" v-on="on">New Item</v-btn>
</template>
<v-card>
<v-card-title>
<span class="headline"> formTitle </span>
</v-card-title>
<v-card-text>
<v-container>
<v-row>
<v-col cols="12" sm="6" md="4">
<v-text-field v-model="editedItem.name" label="Dessert name"></v-text-field>
</v-col>
<v-col cols="12" sm="6" md="4">
<v-text-field v-model="editedItem.calories" label="Calories"></v-text-field>
</v-col>
<v-col cols="12" sm="6" md="4">
<v-text-field v-model="editedItem.fat" label="Fat (g)"></v-text-field>
</v-col>
<v-col cols="12" sm="6" md="4">
<v-text-field v-model="editedItem.carbs" label="Carbs (g)"></v-text-field>
</v-col>
<v-col cols="12" sm="6" md="4">
<v-text-field v-model="editedItem.protein" label="Protein (g)"></v-text-field>
</v-col>
</v-row>
</v-container>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="blue darken-1" text @click="close">Cancel</v-btn>
<v-btn color="blue darken-1" text @click="save">Save</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-toolbar>
</template>
<template v-slot:item.action=" item ">
<v-icon small class="mr-2" @click="editItem(item)">mdi-pencil</v-icon>
<v-icon small @click="deleteItem(item)">mdi-delete</v-icon>
</template>
<template v-slot:no-data>
<v-btn color="primary" @click="initialize">Reset</v-btn>
</template>
</v-data-table>
</template>
<script>
export default
props:
headers:
type: Array
,
items:
type: Array
,
editedItem:
type: Object
,
defaultItem:
type: Object
,
data: () => (
dialog: false,
editedIndex: -1,
),
computed:
formTitle()
return this.editedIndex === -1 ? "New Item" : "Edit Item";
,
watch:
dialog(val)
val || this.close();
,
created ()
this.getParentItem()
,
methods:
getParentItem()
,
editItem(item)
this.editedIndex = this.items.indexOf(item);
this.editedItem = Object.assign(, item);
this.dialog = true;
,
deleteItem(item)
const index = this.items.indexOf(item);
confirm("Are you sure you want to delete this item?") &&
this.items.splice(index, 1);
,
close()
this.dialog = false;
setTimeout(() =>
this.editedItem = Object.assign(, this.defaultItem);
this.editedIndex = -1;
, 300);
,
save()
if (this.editedIndex > -1)
Object.assign(this.items[this.editedIndex], this.editedItem);
else
this.items.push(this.editedItem);
this.close();
;
</script>
【问题讨论】:
【参考方案1】:在组件的created
中添加一些设置为 prop 变量的数据变量。喜欢:
this.internalItems = this.items
this.internalEditedItem = this.editedItem
然后在你的方法中编辑那些而不是 prop 变量。
this.internalEditedItem = Object.assign(, item);
...
Object.assign(this.items[this.editedIndex], this.internalEditedItem);
...etc
如果您打算从父级修改道具,您还需要添加一个监视变量以将它们重置为新值。
【讨论】:
我又遇到了同样的错误,或者我做错了什么,请帮忙....我为此努力了 gist.github.com/panudet-24mb/f3ca188adc45dacfed4883017c8a98ee 我没有时间看你所有的代码,但是这个错误可以通过这样的方式解决。检查每个 prop 以查看是否在方法中对其进行了修改,如果是,则添加一个新的数据变量并使用它来代替 prop以上是关于避免直接改变道具 - Datatable VueJS的主要内容,如果未能解决你的问题,请参考以下文章