我已阅读使用v-for here在列表中呈现自定义组件的文档。
但由于某种原因,我无法使其工作。它总是删除最后一个组件而不是我在索引中发送的组件。知道为什么它不起作用吗?
我的VUE JS版本是:2.5.16。
使用PHPStorm IDE并在docker(linux容器)上运行
和Laravel混合(我在
这是我的一些代码
// Parent Component JS
<template>
<ul>
<li
is="child-component"
v-for="(child, index) in componentList"
:key="index"
:myVal="Something...."
@remove="dropField(index)"
@add-custom-field="addField"
></li>
</ul>
</template>
<script>
import childComponent from './ChildComponent';
export default {
name: 'CustomList',
components: {'child-component' :childComponent},
data() {
return {
componentList: []
}
},
methods: {
addField() {
console.log('Handling add-custom-field field...');
this.componentList.push(childComponent);
},
dropField(index) {
console.log(`I am deleting the component with index = ${index} from listview in parent...`);
this.componentList.splice(index, 1);
}
}
}
// Child Component JS
<template>
<div>
<input type="text" v-model="currentValue" /><button @click.prevent="$emit('remove')" > Remove </button>
</div
</template>
<script>
export default {
props: { myVal : '' },
data() { return { currentValue: ''} },
created() {this.currentValue = this.myVal;}
}
</script>
答案 0 :(得分:2)
问题是由v-for 的就地补丁“策略引起的。这意味着当从componentList中删除一个元素时,Vue不会重建所有子元素。
检查Vue Guide on an “in-place patch” strategy for v-for:
当Vue更新使用v-for,by的呈现的元素列表时 默认情况下,它使用“就地补丁”策略。如果是数据的顺序 项已更改,而不是移动DOM元素以匹配 物品的顺序,Vue将就地修补每个元素并确保 它反映了应该在该特定索引处呈现的内容。
实际上你已经删除了最后一项,但问题是第一个和第二个孩子的data property = currentValue在首次安装时是'a','b'。稍后当Vue重新渲染(删除最后一个子节点)时,虽然prop = myVal已经改变,但data property = currentValue保持相同的值。
看下面的演示,我添加了一个输入并绑定myVal,你会看到差异。
Vue.config.productionTip = false
let childComponent = Vue.component('child', {
template: `<div class="item">
<p>Index:{{parentIndex}} => <button @click.prevent="removed()" > Remove </button>
Data:<input type="text" v-model="currentValue" />Props:<input type="text" v-bind:value="myVal" />
</p>
</div>`,
props: { 'myVal':{
type: String,
default: ''
} ,
'parentIndex': {
type: Number,
default: 0
}
},
data() {
return {
currentValue: ''
}
},
mounted() {
this.currentValue = this.myVal
},
methods: {
removed: function () {
this.$emit('remove')
}
}
})
app = new Vue({
el: "#app",
data() {
return {
componentList: ['a', 'b', 'c'],
componentType:childComponent
}
},
methods: {
addField() {
console.log('Handling add-custom-field field...');
this.componentList.push(childComponent);
},
dropField(index) {
console.log(`I am deleting the component with index = ${index} from listview in parent...`);
this.componentList.splice(index, 1);
}
}
})
li:nth-child(odd) {
background-color:#d0d5dd;
}
<script src="https://unpkg.com/vue@2.5.16/dist/vue.js"></script>
<div id="app">
<ul>
<li v-for="(child, index) in componentList"><div
:is="componentType"
:key="index"
:my-val="child"
:parent-index="index"
@remove="dropField(index)"
@add-custom-field="addField"
>{{child}}</div></li>
</ul>
</div>
答案 1 :(得分:0)
我发现,如果您还有另一个更新的:key
属性(非索引),它将可以根据需要工作
这是我的例子
<template>
<div id="app">
<ul>
<li
v-for="(teacher, index) in teachers_list"
v-bind="teacher"
:key="teacher.id"
>
<p>Teacher id {{teacher.id}}</p>
<button @click="deleteTeacher(index)"></button>
</li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
teachers_list: [
{name: 'teacher a', id: 100},
{name: 'teacher b', id: 200},
{name: 'teacher c', id: 300},
]
}
},
methods: {
deleteTeacher(index) {
console.log(index);
this.teachers_list.splice(index, 1)
}
}
}
</script>