Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
175 views
in Technique[技术] by (71.8m points)

javascript - v-for deletes the wrong element when using array splice despite the use of a unique key

I am currently using v-for to print out the list of 'parties' elements where each 'party' is represented by a <base-card>. When I use the splice() on the additionalInfoList array which represents the array of 'parties' and I log the output on the console, I see that the correct element has been deleted from the array. However, when I observe the output on the screen, Vue somehow manages to delete either the last element of the array or the adjacent element from the list. Based on various suggestions and research, I have used the unique :key to help Vue, but it still gives me this pernicious 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>  

BaseCard.vue

<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>

Output Screen enter image description here


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The code generating ids in the child component creates potentially duplicate ids. On a fast enough machine, all of the ids will be the same:

id: new Date().toISOString()

Remove that and use something truly unique like something based on the v-for index.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...