katerlouis
katerlouis

Reputation: 771

Vue.js 2 remove data (array item) from a corresponding component

enter image description here

I'm making a game.

This is where I struggle. I don't know how to delete the array-item from the data; does "mounted()" know about which array key?

I thought about passing the array-index to the component; the indizes constantly change; coins get added and deleted randomly.

I tried using splice() as suggested in here: How to remove a item from a array Vue.js, but couldn't get it to work.

Since I guess this is a pretty usual use-case I figured if there is a straight forward solution to this.

My html:

<div class="game">

    <xyz v-for="coin in coins" v-bind:data="coin" is="coin"></xyz>

</div>

My js:

// Simplified component
// of course the coin has data like value etc.
Vue.component("coin", {
    props: ["data"],

    template: `
        <div class="sprite">
            <img :src="coin' + data.lane . '.png" />
        </div>
    `,

    mounted () {
        // Sprite animation
        var TweenMax ...
        .eventCallback("onComplete", function() {

            // (!)
            // > delete the data entry, that triggered this rendering  
            // (!)

        })
    }
})

// Vue root instance 
var game = new Vue({
    el: ".game",

    data() {
        coins: [
            { lane: 3 },
            { lane: 2 },
            ...
        ]
    }
})

Upvotes: 0

Views: 634

Answers (1)

Kevin Law
Kevin Law

Reputation: 852

I think you'd better to delete a single coin from array at where coins are maintained(parent component). And in you child component(coin) just need to emit an event to tell the parent component that animation has already completed, please delete me.

BTW, you could set an id for every coin then you can delete them from array by id very easily.

Hope this would be helpful.

// Simplified component
// of course the coin has data like value etc.
Vue.component("xyz", {
    props: ["data"],

    template: `
        <div class="sprite">
            <!-- <img :src="coin' + data.lane . '.png" /> -->
            <div>{{data.lane}}</div>
        </div>
    `,

    mounted () {
         setTimeout(()=>{
            this.$emit('completed', this.data);
         }, 2000);
    }
})


// Vue root instance 
var game = new Vue({
    el: ".game",

    data() {
    return {
        coins: [
            { id: 1,
            lane: 3 },
            { id:2,
            lane: 2 },
        ]
      }
    },
    methods:{
        onCompleted(data){
          for(var c in this.coins){
                   if(this.coins[c].id === data.id){
                        this.coins.splice(c, 1);
                        break;
                   }
         }
          }
    }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<div class="game">

    <xyz v-for="coin in coins" v-bind:data="coin" :key="coin.id" @completed="onCompleted"></xyz>

</div>

Upvotes: 1

Related Questions