我知道如何从Vue实例中删除列表项。但是,当列表项传递给Vue组件时,如何在保持组件与列表数据同步的同时删除列表项?
这是用例。考虑使用Markdown编辑器的在线论坛。我们有一个Vue实例,其数据是从服务器获取的已保存注释的列表。这些评论应该用降价来写。
为了便于编辑和预览,我们还提供了一个组件列表。每个组件都包含一个可编辑的输入缓冲区和一个预览部分。 Vue实例中保存的注释的内容用于初始化输入缓冲区并在用户取消编辑时重置它。预览是输入缓冲区内容的转换。
以下是测试实施:
<template id="comment">
<div>
Component:
<textarea v-model="input_buffer" v-if="editing"></textarea>
{{ preview }}
<button type="button" v-on:click="edit" v-if="!editing">edit</button>
<button type="button" v-on:click="remove" v-if="!editing">remove</button>
<button type="button" v-on:click="cancel" v-if="editing">cancel</button>
</div>
</template>
<div id="app">
<ol>
<li v-for="(comment, index) in comments">
<div>Instance: {{comment}}</div>
<comment
v-bind:comment="comment"
v-bind:index="index"
v-on:remove="remove">
</comment>
</li>
</ol>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.8/vue.js"></script>
<script>
let comments = ['111', '222', '333']
Vue.component('comment', {
template: '#comment',
props: ['comment', 'index'],
data: function() {
return {
input_buffer: '',
editing: false,
}
},
mounted: function() { this.cancel() },
computed: {
preview: function() {
// This is supposed to be a transformation of the input buffer,
// but for now, let's simply output the input buffer
return this.input_buffer
},
},
methods: {
edit: function() { this.editing = true },
remove: function() { this.$emit('remove', this.index) },
cancel: function() { this.input_buffer = this.comment; this.editing = false },
//save: function() {}, // submit to server; not implemented yet
},
})
let app = new Vue({
el: '#app',
data: { comments: comments },
methods: {
remove: function(index) { this.comments.splice(index, 1); app.$forceUpdate() },
},
})
</script>
问题在于,如果我们删除注释,则组件不会相应刷新。例如,我们在上面的实现中有3条评论。如果您删除评论2,则项目3的预览仍将显示第2项的内容。仅当我们按edit
后跟cancel
时才会更新。
我已尝试app.$forceUpdate()
,但这没有用。
答案 0 :(得分:4)
您只需在v-for循环中添加key
属性,如下所示:
<li v-for="(comment, index) in comments" :key="comment">
见工作小提琴:https://fiddle.jshell.net/mimani/zLrLvqke/
Vue尝试优化渲染,通过提供关键属性,将它们视为完全不同的元素并重新渲染它们。
有关详细信息,请参阅the key
documentation。
答案 1 :(得分:0)
尝试:
Vue.component('comment', {
template:
`<div>
{{ comment }}
<button v-on:click="remove"> X </button>
</div>`,
props: ['comment', 'index'],
methods: {
remove: function() {
this.$emit('remove', this.index);
}
},
});
vm = new Vue({
el: '#app',
data: {
comments: ['a','b','c','d','e']
},
methods: {
remove: function(index) {
this.comments.splice(index, 1);
},
},
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.8/vue.min.js"></script>
<div id="app">
<ol>
<li v-for="(comment, index) in comments">
<comment
v-bind:comment="comment"
v-bind:index="index"
v-on:remove="remove">
</comment>
</li>
</ol>
</div>