0

enter image description here

I'm making a game.

  • A controller adds "coins" to the data.
  • When a coin is added, it mounts a component, which html gets animated (simple sprite animation with GSAP)
  • When the animation is over the coin needs to get deleted from the data.

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 },
            ...
        ]
    }
})
3
  • Please aslo provide any fiddle/live demo ? Commented Apr 16, 2018 at 10:14
  • Hard to extract this out of the full project, which obviously isn't working and has way more data etc. pp. – What exactly don't you understand? I basically need to delete the object in the main app's data.coins-array, that triggered the mounted() function of the component. But I can't get mounted() to know about it's corresponding array-item. Commented Apr 16, 2018 at 10:26
  • Do you have any git repo of this? Commented Apr 16, 2018 at 10:48

1 Answer 1

1

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>

Sign up to request clarification or add additional context in comments.

10 Comments

What you describe in your first sentence is exactly what I'm trying to do, but I don't know how. Could you update your answer with a code example of how you would emit the event?
I thought about the id aswell, but don't know a convenient way creat unique IDs, unless add a counter to the main app, which would clutter everything even more. Maybe, just for learning purposes, you could illustrate that solution aswell? Thank you!
I've updated my answer with code snippet, as well the id solution.
Thank you! Still got questions, though: 1) Is there a reason why you changed my image to <div>{{ data.lane }}</div>? 2) You talked about 2 solutions, the code example covers just the ID way, right? 3) how would you add coins and ensure that the ID is unique? 4) why do you have to do @completed="onCompleted"? Couldn't you just $emit to onCompleted directly?
1. You can ignore it, I was just trying to display something. Image will broken as I don't have those images. 2. Yes, also you can save an index to a local variable when adding it. 3. There are many ways to achieve that, for example you can use some 3rd party library likes uuid to generate a unique id or even simply use current Unix timestamp as a unique id. 4. emit is fire the event in child component while @completed="onCompleted" is bind a event handler for parent component. This is the stand way communicate from child component to parent.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.