37 Degres
37 Degres

Reputation: 201

Vue 3.0 router components transition does not work with mode="out-in"

I building an application with vue 3.0 and vue-router 4.0.

I have this very simple code in my App.vue component (first rendered component) :

<router-view v-slot="{ Component }">
    <transition name="fade" mode="out-in" appear>
        <component :is="Component"></component>
    </transition>
</router-view>

First page is renderer - no problem. But as soon as I navigate to another page, page become blank. If I remove the mode="out-in" it works (but transition is ugly).

Does anyone know why ?

Upvotes: 4

Views: 3760

Answers (4)

Nick C
Nick C

Reputation: 420

Since it seems to still be an issue as February 2024 (albeit with a couple of possible fixes in Vue's pull requests), I think it's worth clarifying that <transition> seems to treat top/root-level comments as if they are actual HTML nodes.

As others have noted, <transition> only supports a single element or component. As a result, if you are using it as follows:

<transition name="fade">
  <SomeComponent />
</transition>

And <SomeComponent /> has a template as follows:

<template>
  <!-- Some comment -->
  <div> My Content </div>
</template>

That single comment will cause any transitions you apply to fail. It will even fail if you move the comment under the div in the template of <SomeComponent />

The fix is simple enough:

<template>
  <div>
    <!-- Some comment -->
    My Content 
  </div>
</template>

Of course, these cases are fairly easy to notice even if the error isn't obvious.

BUT it is much less obvious when dealing with Vue-Router, in particular when you use the following common pattern:

<router-view v-slot="{ Component, route }">
  <Transition :name="route.meta.transition" mode="out-in">
    <component :is="Component" />
  </Transition>
</router-view>

Now every possible Route's component that has a top/root-level comment can cause the issue to arise.

Similarly, the issue can appear if you're using a container/wrapper component without any comments.

Let's say we had <ContainerComponent /> that provides special styling to <SomeComponent /> in the root of the template, it may be easy to miss that the issue is due to the child <SomeComponent />

Hopefully this reaches and helps anyone who may be having this issue!

Upvotes: 1

FreezeNow
FreezeNow

Reputation: 41

The reason for this problem is that transition only supports a single element. The official document hints:

<Transition> only supports a single element or component as its slot content. 
If the content is a component, the component must also have only one single root element.

You can see a demo in this link: https://stackblitz.com/edit/vitejs-vite-gwfbmb?file=src%2FApp.vue

Upvotes: 4

3ximus
3ximus

Reputation: 400

Each template can only have one tag (element). The following example would break the transitions

<template>
  <div class="about"></div>
  <img class="back-img" src="/artwork/58.webp"/>
</template>

Upvotes: 5

37 Degres
37 Degres

Reputation: 201

I finally found were the mistake was, and how stupid it was...

In my template, I put a comment before the first tag:

<template>

    <!-- login layout --> <=== NOT A GOOD IDEA...
    <div class="lsn-login">
        ...
    </div>

</template>

Thank you for all your comment.

Upvotes: 16

Related Questions