Javascript 尽管使用了唯一键,但v-for在使用阵列拼接时删除了错误的元素
我目前正在使用Javascript 尽管使用了唯一键,但v-for在使用阵列拼接时删除了错误的元素,javascript,arrays,vue.js,vue-component,v-for,Javascript,Arrays,Vue.js,Vue Component,V For,我目前正在使用v-for打印“参与方”元素列表,其中每个“参与方”由表示。当我在表示“参与方”数组的附加信息列表上使用splice()并在控制台上记录输出时,我发现已从数组中删除了正确的元素。但是,当我观察屏幕上的输出时,Vue设法从列表中删除数组的最后一个元素或相邻元素。基于各种建议和研究,我使用了独特的:key来帮助Vue,但它仍然给了我这个有害的bug BaseCardList.vue <template> <div> <ul>
v-for
打印“参与方”元素列表,其中每个“参与方”由
表示。当我在表示“参与方”数组的附加信息列表上使用splice()
并在控制台上记录输出时,我发现已从数组中删除了正确的元素。但是,当我观察屏幕上的输出时,Vue设法从列表中删除数组的最后一个元素或相邻元素。基于各种建议和研究,我使用了独特的:key
来帮助Vue,但它仍然给了我这个有害的bug
BaseCardList.vue
<template>
<div>
<ul>
<base-card v-once
@add-parties="updateAdditionalInfoList"
@delete-party="deleteParty">
<template v-slot:title>
<slot></slot>
</template>
</base-card>
<base-card
v-for="(data) in additionalInfoListComputed" :key="JSON.stringify(data.id)"
ref="childComponent"
@add-parties="updateAdditionalInfoList"
@delete-party="deleteParty">
<!-- Wrapper for the `Parties Being Served` component-->
<template v-slot:title>
<slot></slot>
</template>
</base-card>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
selectedComponent: 'base-card',
additionalInfoList : [],
clearForm: false,
counter: 0
}
},
computed : {
additionalInfoListComputed(){
console.log('state changed');
return this.additionalInfoList;
}
},
methods: {
updateAdditionalInfoList(additionalInfo){
this.additionalInfoList.push(additionalInfo);
this.counter++;
console.log('The length is'+this.additionalInfoList.length);
},
deleteParty(resId){
const resIndex = this.additionalInfoList.findIndex(
res => res.id === resId
);
this.additionalInfoList.splice(resIndex, 1);
console.log('Index is '+resIndex);
console.log(this.additionalInfoList);
}
}
}
</script>
<style scoped>
ul{
align-content: left;
padding: 0
}
</style>
<template>
--something
</template>
<script>
import { EventBus } from './bus.js';
export default {
emits:['add-parties','delete-party'],
data() {
return {
additionalInfo:
{
id: new Date().toISOString(),
fullName: '',
preAuthorize: '',
serviceAddress: ''
},
validation: {
fullNameIsValid: true,
serviceAddressIsValid: true
},
hideAddButton: false,
formIsValid: true,
addServiceButtonText: '+ Add Service Notes (Optional)',
serviceNotes: [],
showServiceNotes: false,
showDeleteButton: true,
enteredServiceNote: '', //service notes addendum
}
},
computed : {
showServiceNotex(){
if(!this.showServiceNotes){
return '+Add Service Notes (Optional)'
}else{
return '- Remove Service Notes';
}
}
},
methods: {
setServiceNotes(){
this.showServiceNotes = !this.showServiceNotes;
},
addAnotherParty(){
this.validateForm();
if(!this.formIsValid){
return;
}
let emitObj = JSON.parse(JSON.stringify(this.additionalInfo));
this.$emit('add-parties', emitObj); //event
this.hideAddButton = !this.hideAddButton;
console.log(this.hideAddButton);
},
deleteParty(){
this.$emit('delete-party', this.additionalInfo.id);
},
validateForm(){
this.formIsValid = true;
if(this.additionalInfo.fullName === ''){
this.validation.fullNameIsValid = false;
this.formIsValid = false;
}
if(this.additionalInfo.serviceAddress === ''){
this.validation.serviceAddressIsValid = false;
this.formIsValid = false;
}
},
clearValidity(input){
this.validation[input] = true;
},
clearForm(){
this.additionalInfo.fullName = '';
this.additionalInfo.serviceAddress = '';
this.additionalInfo.preAuthorize = false;
}
},
created(){
console.log('created');
console.log(this.hideAddButton);
}
}
</script>
导出默认值{
数据(){
返回{
selectedComponent:'基本卡',
附加信息列表:[],
clearForm:false,
柜台:0
}
},
计算:{
additionalInfoListComputed(){
log('state changed');
返回此.additionalInfoList;
}
},
方法:{
UpdateAdditionalInvolist(附加信息){
this.additionalInfoList.push(additionalInfo);
这个.counter++;
log('长度为'+this.additionalInfoList.length);
},
删除方(剩余){
const resIndex=this.additionalInfoList.findIndex(
res=>res.id==resId
);
此.additionalInfoList.splice(resIndex,1);
log('索引为'+resIndex);
console.log(this.additionalInfoList);
}
}
}
保险商实验室{
对齐内容:左对齐;
填充:0
}
BaseCard.vue
<template>
<div>
<ul>
<base-card v-once
@add-parties="updateAdditionalInfoList"
@delete-party="deleteParty">
<template v-slot:title>
<slot></slot>
</template>
</base-card>
<base-card
v-for="(data) in additionalInfoListComputed" :key="JSON.stringify(data.id)"
ref="childComponent"
@add-parties="updateAdditionalInfoList"
@delete-party="deleteParty">
<!-- Wrapper for the `Parties Being Served` component-->
<template v-slot:title>
<slot></slot>
</template>
</base-card>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
selectedComponent: 'base-card',
additionalInfoList : [],
clearForm: false,
counter: 0
}
},
computed : {
additionalInfoListComputed(){
console.log('state changed');
return this.additionalInfoList;
}
},
methods: {
updateAdditionalInfoList(additionalInfo){
this.additionalInfoList.push(additionalInfo);
this.counter++;
console.log('The length is'+this.additionalInfoList.length);
},
deleteParty(resId){
const resIndex = this.additionalInfoList.findIndex(
res => res.id === resId
);
this.additionalInfoList.splice(resIndex, 1);
console.log('Index is '+resIndex);
console.log(this.additionalInfoList);
}
}
}
</script>
<style scoped>
ul{
align-content: left;
padding: 0
}
</style>
<template>
--something
</template>
<script>
import { EventBus } from './bus.js';
export default {
emits:['add-parties','delete-party'],
data() {
return {
additionalInfo:
{
id: new Date().toISOString(),
fullName: '',
preAuthorize: '',
serviceAddress: ''
},
validation: {
fullNameIsValid: true,
serviceAddressIsValid: true
},
hideAddButton: false,
formIsValid: true,
addServiceButtonText: '+ Add Service Notes (Optional)',
serviceNotes: [],
showServiceNotes: false,
showDeleteButton: true,
enteredServiceNote: '', //service notes addendum
}
},
computed : {
showServiceNotex(){
if(!this.showServiceNotes){
return '+Add Service Notes (Optional)'
}else{
return '- Remove Service Notes';
}
}
},
methods: {
setServiceNotes(){
this.showServiceNotes = !this.showServiceNotes;
},
addAnotherParty(){
this.validateForm();
if(!this.formIsValid){
return;
}
let emitObj = JSON.parse(JSON.stringify(this.additionalInfo));
this.$emit('add-parties', emitObj); //event
this.hideAddButton = !this.hideAddButton;
console.log(this.hideAddButton);
},
deleteParty(){
this.$emit('delete-party', this.additionalInfo.id);
},
validateForm(){
this.formIsValid = true;
if(this.additionalInfo.fullName === ''){
this.validation.fullNameIsValid = false;
this.formIsValid = false;
}
if(this.additionalInfo.serviceAddress === ''){
this.validation.serviceAddressIsValid = false;
this.formIsValid = false;
}
},
clearValidity(input){
this.validation[input] = true;
},
clearForm(){
this.additionalInfo.fullName = '';
this.additionalInfo.serviceAddress = '';
this.additionalInfo.preAuthorize = false;
}
},
created(){
console.log('created');
console.log(this.hideAddButton);
}
}
</script>
--某物
从'/bus.js'导入{EventBus};
导出默认值{
发出:[“添加方”、“删除方”],
数据(){
返回{
其他信息:
{
id:new Date().toISOString(),
全名:“”,
预授权:'',
服务地址:“”
},
验证:{
fullNameIsValid:true,
serviceAddressIsValid:true
},
隐藏按钮:false,
福米斯瓦利德:是的,
addServiceButtonText:“+添加服务说明(可选)”,
服务说明:[],
showServiceNotes:false,
showDeleteButton:true,
enteredServiceNote:“”,//服务说明附录
}
},
计算:{
showServiceNotex(){
如果(!this.showServiceNotes){
返回“+添加维修说明(可选)”
}否则{
返回“-删除维修注释”;
}
}
},
方法:{
setServiceNotes(){
this.showServiceNotes=!this.showServiceNotes;
},
另一方{
这是validateForm();
如果(!this.formIsValid){
返回;
}
让emitObj=JSON.parse(JSON.stringify(this.additionalInfo));
此.emit('add-parties',emitObj);//事件
this.hideAddButton=!this.hideAddButton;
console.log(this.hideAddButton);
},
删除方(){
此.emit('delete-party',this.additionalInfo.id);
},
validateForm(){
this.formIsValid=true;
如果(this.additionalInfo.fullName==''){
this.validation.fullNameIsValid=false;
this.formIsValid=false;
}
如果(this.additionalInfo.serviceAddress==''){
this.validation.serviceAddressIsValid=false;
this.formIsValid=false;
}
},
clearValidity(输入){
this.validation[input]=true;
},
clearForm(){
this.additionalInfo.fullName='';
this.additionalInfo.serviceAddress='';
this.additionalInfo.preAuthorize=false;
}
},
创建(){
console.log('created');
console.log(this.hideAddButton);
}
}
输出屏幕
您应该将索引传递给delete方法deleteParty
<base-card v-for="(data,index) in additionalInfoListComputed" :key="JSON.stringify(data.id)" ref="childComponent"
@add-parties="updateAdditionalInfoList" @delete-party="deleteParty(index)">
<!-- Wrapper for the `Parties Being Served` component-->
<template v-slot:title>
<slot></slot>
</template>
</base-card>
在子组件中生成ID的代码可能会创建重复的ID。在速度足够快的机器上,所有ID都将相同:
id: new Date().toISOString()
删除它并使用真正独特的东西,比如基于v-for
索引的东西