我正在使用计算列表显示几种形式,用于更改数据库中的注释。 (通过axios的后端Symfony / api请求,但不相关)
注释本身的表单位于Vue组件中。 计算的列表基于一个列表,该列表在装入页面时被加载(并设置为data属性),然后由计算的属性中的输入搜索框过滤该列表。
现在,当我在输入框中键入不同的内容并且注释组件得到更新时,v模型和标签混乱了。
我已经在几种浏览器中进行了测试,并且在主要浏览器中的行为相同。
我还搜索了文档,但没有找到解决方案。
再现行为的示例:
<!DOCTYPE html>
<html>
<div id="app"></app>
</html>
const ChangeCommentForm = {
name: 'ChangeCommentForm',
props: ['comment', 'id'],
data() {
return {
c: this.comment,
disabled: false
};
},
template: `
<form>
<div>{{ comment }}</div>
<input :disabled="disabled" type="text" v-model="c">
<button type="submit" @click.prevent="changeComment">
Change my comment
</button>
</form>
`,
methods: {
changeComment() {
this.disabled = true;
// do the actual api request (should be unrelated)
// await api.changeCommentOfFruit(this.id, this.c),
// replacing this with a timeout for this example
window.setTimeout(() => this.disabled = false, 1000);
}
}
};
const App = {
components: {ChangeCommentForm},
data() {
return {
fruits: [
{id: 1, text: "apple"},
{id: 2, text: "banana"},
{id: 3, text: "peach"},
{id: 4, text: "blueberry"},
{id: 5, text: "blackberry"},
{id: 6, text: "mango"},
{id: 7, text: "watermelon"},
],
search: ''
}
},
computed: {
fruitsFiltered() {
if (!this.search || this.search === "")
return this.fruits;
const r = [];
for (const v of this.fruits)
if (v.text.includes(this.search))
r.push(v);
return r;
}
},
template: `
<div>
<form><input type="search" v-model="search"></form>
<div v-for="s in fruitsFiltered">
<ChangeCommentForm :id="s.id" :comment="s.text"/>
</div>
</div>
`
};
const vue = new Vue({
el: '#app',
components: {App},
template: '<app/>'
});
只需在搜索框中输入一些字母 有关代码笔的示例:https://codepen.io/anon/pen/KLLYmq
现在如示例中所示,CommentChangeForm中的div已正确更新,但是v模型已损坏。
我想知道我是否错过了什么,或者这是Vue中的错误?
答案 0 :(得分:1)
为了在渲染之间保留DOM元素的状态,重要的是v-for
元素还具有key
属性。渲染之间的此键应保持一致。
在这里看来,以下方法可以解决问题:
<div v-for="s in fruitsFiltered" :key="s.id">
<ChangeCommentForm :id="s.id" :comment="s.text"/>
</div>
请参阅: