Vue.js - 使用子组件更新或撤消模式
Vue.js - Updated or undo pattern with child component
我在从子组件更新正确的对象时遇到问题。
我的设置如下:
一个 ul 列表,其中包含我要呈现或编辑的大部分数据。
在"li"的一部分上,有一个子组件来展示那部分数据,也就是那个对象连接的资源列表,同时也处理新资源的推送。
我还希望用户有一个用于启用行编辑模式的按钮,然后是用于更新和取消的按钮。
我面临的问题是找出我应该编辑然后保存的对象。我现在正在做的是尝试将行中的数据复制到一个 mutableRow 中,然后我将其用作输入控件的模型,而当用户未处于编辑模式时显示实际的行数据。在更新方法中,我 post 到数据库并更新了行对象。
ul
li(v-for="row in rows")
p(v-if="!row.editing") {{ row.name }}
input(v-else, v-model="mutableRow.name")
resources(:row="row")
button(v-if="!row.editing") Start edit
template(v-else)
button Update
button Cancel
这是正确的做法吗?如果是这样,我应该如何处理发送到我的子组件的道具?我尝试通过 this.$parent.mutableRow 获取 mutableRow,我尝试使用 v-if 切换 "resource(:row="row")" 并在编辑模式下发送 mutableRow,但随后我结束了以某种方式更改组件中的两个对象。
我可以在这里使用其他模式吗?
我认为您提到的 "mutable row" 问题可以通过传递 rows[index]
而不是 row
来解决。无论如何,这就是 .sync
工作所需要的。
我下面的例子实现了我在评论中的建议:一个单独的组件,它有自己的数据副本和自己的编辑模式控件。当您开始编辑时,道具数据被复制到本地数据。单击“更新”时,会发出一个事件,父级(通过 sync
)将编辑的数据复制到行中。如果单击取消,则不会发出任何事件,编辑结束。
new Vue({
el: '#app',
data: {
rows: [{
name: "Test",
thingy: 4,
resources: [{
title: "Title",
price: 5000
}]
}]
},
components: {
rowEditor: {
template: '#row-editor-t',
props: ['row'],
data() {
return {
editing: false,
localRow: null
};
},
methods: {
startEditing() {
this.editing = true;
this.localRow = JSON.parse(JSON.stringify(this.row));
},
stopEditing() {
this.editing = false;
},
update() {
this.$emit('update:row', this.localRow);
this.stopEditing();
},
cancel() {
this.stopEditing();
}
}
}
}
});
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script>
<div id="app">
<ul>
<li v-for="row, index in rows" is="row-editor" :row.sync="rows[index]">
</li>
</ul>
</div>
<template id="row-editor-t">
<li>
<div v-if="editing">
<input v-model="localRow.name">
<div v-for="resource in localRow.resources">
<input v-model="resource.title"><input v-model="resource.price">
</div>
</div>
<div v-else>
{{row.name}}
<div v-for="resource in row.resources">
{{resource.title}}: {{resource.price}}
</div>
</div>
<div v-if="editing">
<button type="button" @click="update">Update</button>
<button type="button" @click="cancel">Cancel</button>
</div>
<button v-else @click="startEditing">Start edit</button>
</li>
</template>
<!--
ul
li(v-for=" row in rows ")
p(v-if="!row.editing ") {{ row.name }}
input(v-else, v-model="mutableRow.name ")
resources(:row="row ")
button(v-if="!row.editing ") Start edit
template(v-else)
button Update
button Cancel
-->
我在从子组件更新正确的对象时遇到问题。
我的设置如下: 一个 ul 列表,其中包含我要呈现或编辑的大部分数据。 在"li"的一部分上,有一个子组件来展示那部分数据,也就是那个对象连接的资源列表,同时也处理新资源的推送。
我还希望用户有一个用于启用行编辑模式的按钮,然后是用于更新和取消的按钮。
我面临的问题是找出我应该编辑然后保存的对象。我现在正在做的是尝试将行中的数据复制到一个 mutableRow 中,然后我将其用作输入控件的模型,而当用户未处于编辑模式时显示实际的行数据。在更新方法中,我 post 到数据库并更新了行对象。
ul
li(v-for="row in rows")
p(v-if="!row.editing") {{ row.name }}
input(v-else, v-model="mutableRow.name")
resources(:row="row")
button(v-if="!row.editing") Start edit
template(v-else)
button Update
button Cancel
这是正确的做法吗?如果是这样,我应该如何处理发送到我的子组件的道具?我尝试通过 this.$parent.mutableRow 获取 mutableRow,我尝试使用 v-if 切换 "resource(:row="row")" 并在编辑模式下发送 mutableRow,但随后我结束了以某种方式更改组件中的两个对象。
我可以在这里使用其他模式吗?
我认为您提到的 "mutable row" 问题可以通过传递 rows[index]
而不是 row
来解决。无论如何,这就是 .sync
工作所需要的。
我下面的例子实现了我在评论中的建议:一个单独的组件,它有自己的数据副本和自己的编辑模式控件。当您开始编辑时,道具数据被复制到本地数据。单击“更新”时,会发出一个事件,父级(通过 sync
)将编辑的数据复制到行中。如果单击取消,则不会发出任何事件,编辑结束。
new Vue({
el: '#app',
data: {
rows: [{
name: "Test",
thingy: 4,
resources: [{
title: "Title",
price: 5000
}]
}]
},
components: {
rowEditor: {
template: '#row-editor-t',
props: ['row'],
data() {
return {
editing: false,
localRow: null
};
},
methods: {
startEditing() {
this.editing = true;
this.localRow = JSON.parse(JSON.stringify(this.row));
},
stopEditing() {
this.editing = false;
},
update() {
this.$emit('update:row', this.localRow);
this.stopEditing();
},
cancel() {
this.stopEditing();
}
}
}
}
});
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script>
<div id="app">
<ul>
<li v-for="row, index in rows" is="row-editor" :row.sync="rows[index]">
</li>
</ul>
</div>
<template id="row-editor-t">
<li>
<div v-if="editing">
<input v-model="localRow.name">
<div v-for="resource in localRow.resources">
<input v-model="resource.title"><input v-model="resource.price">
</div>
</div>
<div v-else>
{{row.name}}
<div v-for="resource in row.resources">
{{resource.title}}: {{resource.price}}
</div>
</div>
<div v-if="editing">
<button type="button" @click="update">Update</button>
<button type="button" @click="cancel">Cancel</button>
</div>
<button v-else @click="startEditing">Start edit</button>
</li>
</template>
<!--
ul
li(v-for=" row in rows ")
p(v-if="!row.editing ") {{ row.name }}
input(v-else, v-model="mutableRow.name ")
resources(:row="row ")
button(v-if="!row.editing ") Start edit
template(v-else)
button Update
button Cancel
-->