Vue: destroy hook is called before transition finishes

Created on 1 Nov 2017  路  7Comments  路  Source: vuejs/vue

Version

2.5.2

Reproduction link

https://codepen.io/autumnwoodberry/pen/yPNdRB

Steps to reproduce

  • Click the "toggle" button.
  • Notice that the "destroyed" hook of the transitioning component has been executed before the transition is complete.

What is expected?

destroyed hook is not executed until after the transition is complete

What is actually happening?

destroyed hook is executed before transition is complete


https://forum.vuejs.org/t/vue-destroys-components-on-a-page-when-they-are-still-needed/20560/4

Most helpful comment

@autumnwoodberry Thanks, but this is a kind of a workaround though. For example, if a transition is not used, then transitionend is not triggered. And in your example transition is applied directly to a component, not to a parent component (a page, for example). Component shouldn't know the parent container uses a transition or not. I believe, some strong and straightforward event needed, which will help us to detect the last moment when the component really is not needed anymore and we can destroy it.

All 7 comments

This is expected behavior. Think of it the other way around: the leave transition is triggered by the removal of the element. Transition state is ephemeral and does not reflect Virtual DOM state - in the virtual DOM the element is considered to be already destroyed.

If you want to do something when the element is finally removed in real DOM, use transition hooks instead.

@yyx990803
How to incapsulate destroying or "garbage collecting" inside components?
What hook inside components to use to destroy components _after_ transition of the parent page finishes?
Here is the screencast: http://take.ms/70FsB
This is an illustration of a problem which is caused by such behavior.

@plashenkov I believe @yyx990803 is referring to using 'transitionend': https://codepen.io/autumnwoodberry/pen/RjWoWb?editors=1111

@autumnwoodberry Thanks, but this is a kind of a workaround though. For example, if a transition is not used, then transitionend is not triggered. And in your example transition is applied directly to a component, not to a parent component (a page, for example). Component shouldn't know the parent container uses a transition or not. I believe, some strong and straightforward event needed, which will help us to detect the last moment when the component really is not needed anymore and we can destroy it.

Is there a known "best practice" how to wait for the transitions to finish when they are "outside" of the current component - e.g. a page transition around vue-router?

Example: I need to wait for the page transitions to fix: https://github.com/staskjs/vue-slick/issues/56

I made a mixin to work around this issue: https://www.npmjs.com/package/vue-removed-hook-mixin

Another side problem is that :

When using with router-view

<transition mode="out-in">
  <router-view/>
</transition>

If the <router-view> contains any <router-link> (which is very likely), then when the transition starts, by destroying the view, it also destroys the children links, so they don't work as expected anymore and don't get the active CSS classes applied, whereas the router-view is still visible in the screen.
Which leads to a transition with no style for the active links (= bad when you want that to be styled).

A workaround is to fix the links manually on all router-views :

{
    ...
    beforeRouteLeave(to, from, next) {
        for (let link of this.$el.querySelectorAll(`a[href="${to.path}"]`))
            link.classList.add('router-link-exact-active')
        next()
    }
}

Not clean for a Vue app, but if someone has a better solution...

Was this page helpful?
0 / 5 - 0 ratings