1

To do something after the DOM has been updated by Vue, you use the $nextTick binding.

To do something after a css transition has completed, you can use transitionend event.

I have a dynamic list in which things are added and removed by user actions. When removed, there is a CSS animation and then I need to check the state of the DOM immediately after the element is gone.

I was thinking that the $nextTick after the transitionend would be the state of the DOM immediately after the list item is removed, but it is not.

I need to do something after the transition has ended and the element from a list has been removed from the DOM.

Right now I have:

<transition-group class="message-bus" tag="ul" name="message-bus">
    <li v-for="message in messages" v-bind:key="message.id" :ref="message.id">
        <div>{{message.text}}</div>
        <a class="dismiss-message" @click="dismissMessage(message)">&times;</a>
    </li>
</transition-group>

dismissMessage(message){
    const vm = this;

    this.$refs[message.id][0].addEventListener("transitionend", function(){
        vm.$nextTick(function(){
            //This is called, but appears to be called before the element is actually removed from the DOM
            //I need to query the DOM immediately after this element is removed 
        });
    });

    this.messages.splice(this.messages.indexOf(message), 1);

}
Randy Hall
  • 7,716
  • 16
  • 73
  • 151

2 Answers2

1

In the mounted function, I have added a MutationObserver that appears to be working as needed. I'll put this here as an answer as it does technically work and may be helpful to others, but I'm still interested in a better answer if Vue has something built in for this.

mounted(){
    const vm = this;
    const listItemRemoved = new MutationObserver(function(e){
        if (e[0].removedNodes.length){
            console.log("Removed");
        }
    });
    listItemRemoved.observe(this.$el, {childList: true});
}
Randy Hall
  • 7,716
  • 16
  • 73
  • 151
1

Perhaps you could use a custom directive. Perform the actions you need inside the unbind hook ..

created() {
    this.vm = this
},
directives: {
  foo: {
    unbind(el, binding) {
      // Here you can perform the actions you need.
      // You can access the Vue instance using binding.value (eg: binding.value.$el)
    }
  }
},

And in your template ..

<transition-group class="message-bus" tag="ul" name="message-bus">
    <li v-for="message in messages" v-bind:key="message.id" :ref="message.id" v-foo="vm">
        <div>{{message.text}}</div>
        <a class="dismiss-message" @click="dismissMessage(message)">&times;</a>
    </li>
</transition-group>
tony19
  • 125,647
  • 18
  • 229
  • 307
Husam Ibrahim
  • 6,999
  • 3
  • 16
  • 28