我有几个手风琴(每个手风琴都是一个Vue组件),默认情况下它们是扩展的。还有一个“复制”功能,允许复制每个组件。
Vue.component("Accordion", {
template: "#accordion-template",
data: function () {
return {
open: true
}
},
methods: {
toggle: function () {
this.open = !this.open;
}
}
});
new Vue({
el: '#vue-root',
data: {
devices: [
{
name: "a", description: "first"
},
{
name: "b", description: "second"
},
{
name: "c", description: "third"
}
]
},
methods: {
copy: function (device) {
var index = this.devices.indexOf(device) + 1;
var copy = {
name: device.name + "_copy",
description: device.description + "_copy"
};
this.devices.splice(index, 0, copy);
}
}
});<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.4/vue.js"></script>
<div id="vue-root">
<div class="device" v-for="device in devices">
<accordion>
<div slot="acc-head">
<span>{{ device.name }}</span><br/>
<button @click="copy(device)">copy</button>
</div>
<div slot="acc-body">
{{ device.description }}
</div>
</accordion>
</div>
</div>
<script type="text/x-template" id="accordion-template">
<div>
<slot name="acc-head"></slot>
<button @click="toggle">Open: {{ open }}</button>
<div :class="open ? 'active' : 'hidden'">
<slot name="acc-body"></slot>
</div>
</div>
</script>
当所有手风琴都被折叠(换句话说,'open: false')并且我试图从列表中间复制手风琴(例如b)时,我希望出现名为'name'_copy的新组件,它必须在默认情况下展开。但是,新组件的所有属性的值与重复的属性值相同,列表中的最后一个组件将被展开。
我怎样才能解决这个问题?
发布于 2019-03-21 10:59:04
简短回答
在v-for循环中添加一个键:v-for="device in devices" :key="{something here}"。您的密钥必须是唯一的,并且识别每个设备,即使是在设备复制之后。
代码
请查收:un/9 9cradxvp/。为了调试的目的,我改变了一些东西:
device作为props of <accordion>,以便在console.log中使用设备属性<accordion>发出。关于侦听子组件事件的Vue docmounted()和updated()钩子。更多关于生命周期钩的信息长答案
关于列表呈现
如果在v-for循环中没有提供密钥,Vue不知道如何更新列表。来自Vue文档
为了给Vue一个提示,以便它能够跟踪每个节点的标识,从而重用和重新排序现有的元素,您需要为每个项提供一个唯一的键属性。
让我们考虑一下您的列表(我添加了一个元素)
[
{id: 1, name: "a"},
{id: 2, name: "b"},
{id: 3, name: "c"},
{id: 4, name: "d"},
]现在,让我们复制节点"b“。如果没有:key="device.id",控制台输出是
4: d is mounted
3: c is updated
5: b_copy is updated对于:key="device.id",控制台输出仅为:
5: b_copy is mounted基本上,没有钥匙,就有:
c变成b_copy,d变成cd因此,每次处理副本时都会重新创建最后一个元素。由于open默认值是true,显然,d有open = true。
如果每个元素都有一个:key="device.id",那么只创建元素b_copy。
要检查这一点,请从我的小提琴中移除:key="device.id",并查看控制台中发生了什么。
选择密钥
由于键必须唯一地标识设备,因此当您复制设备时,不应将索引用作数组更改中的设备索引。
此外,首选ID字段,因为无法保证设备名称是唯一的。如果您初始化列表时
[
{ name: "a"},
{ name: "b"},
{ name: "a"}
]从功能的角度来看,这是正确的。
发布于 2019-03-21 10:42:15
在使用Vue和lists时,应该向带有Vue的元素中添加一个钥匙支柱。使用这样的键,让我们知道您指的是一个特定的元素。
<div class="device" v-for="device in devices" :key="device.name">我认为原因在于,由于性能原因,Vue默认添加一个新元素作为最后一个元素,然后更新其他节点中的数据。因此,添加的新元素实际上是列表中的最后一个元素,其打开集为true。
发布于 2019-03-21 11:02:16
在您的代码中添加一点:
您可以直接传递索引,而不是提供"device“对象并搜索其索引。
这就是我的意思:jsFiddle
Vue.component("Accordion", {
template: "#accordion-template",
data: function() {
return {
open: true
}
},
methods: {
toggle: function() {
this.open = !this.open;
}
}
});
new Vue({
el: '#vue-root',
data: {
devices: [{
name: "a",
description: "first"
},
{
name: "b",
description: "second"
},
{
name: "c",
description: "third"
},
]
},
methods: {
copy: function(index) {
var device = this.devices[index];
var copy = {
name: device.name + "_copy",
description: device.description + "_copy"
};
this.devices.splice(index + 1, 0, copy);
},
remove: function(index) {
this.devices.splice(index, 1);
}
}
});.device {
margin: 10px 0;
}
.active {
display: block;
}
.hidden {
display: none;
}
div.device {
border: 1px solid #000000;
box-shadow: 1px 1px 2px 1px #a3a3a3;
width: 300px;
padding: 5px;
}<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="vue-root">
<div class="device" v-for="(device, index) in devices" :key="device.name">
<accordion>
<div slot="acc-head">
<span>{{ device.name }}</span><br/>
<button @click="copy(index)">copy</button>
<button @click="remove(index)">remove</button>
</div>
<div slot="acc-body">
{{ device.description }}
</div>
</accordion>
</div>
</div>
<script type="text/x-template" id="accordion-template">
<div>
<slot name="acc-head"></slot>
<button @click="toggle">Open: {{ open }}</button>
<div :class="open ? 'active' : 'hidden'">
<slot name="acc-body"></slot>
</div>
</div>
</script>
https://stackoverflow.com/questions/55277559
复制相似问题