jamawe
jamawe

Reputation: 256

:key attribute on parent router-view causes leave (out) transition to fail in nested router-view

What is expected

I have a tabbed navigation in one of my views which triggers nested router-views to be displayed. For these nested routes I want to apply a fade transition. I expect the transition to happen with mode out-in, so that the old router-view first fades out and then the new one fades in.

What is happening

Only the in transition of the out-in mode works: When clicking on a navigation tab the old router-view disappears without transition, but the new one fades in as desired.

When I remove the :key="$route.fullPath" attribute of the parent router-view in App.vue (see below), the nested transitions work fine. But since I re-use router components I definitely need a key attribute on my outer router-view.
Also you should know that without the appear attribute and the keep-alive around the nested router-view no transition would happen at all. I adjusted my code so far according to this issue on GitHub.
How can I manage to both keep the key on the router-view in App.vue and make the transition in the nested view work?

App.vue

<div class="main-wrapper">
  <router-view :key="$route.fullPath" />
</div>

Profile.vue (where nested transitions should happen)

<div class="profile__main">
  <router-view v-slot="{ Component }">
    <Transition name="fade" mode="out-in" appear>
      <keep-alive>
        <component :is="Component"></component>
      </keep-alive>
    </Transition>
  </router-view>
</div>

[...]

.fade-enter-from, .fade-leave-to {
    opacity: 0;
}

.fade-leave-active {
    transition-duration: 500ms;
    transition-property: all;
    transition-timing-function: ease;
}

.fade-enter-active {
    transition-duration: 300ms;
    transition-property: all;
    transition-timing-function: ease;
}

router/index.js

{
    path: '/profile',
    name: 'Profile',
    component: Profile,
    meta: {
      requiresAuth: true,
      title: 'Your Profile',
    },

    children: [
      {
        path: '',
        name: 'ProfileOverview',
        component: ProfileOverview,
      },
      {
        path: 'settings',
        name: 'ProfileSettings',
        component: ProfileSettings,
        meta: {
          title: 'Your Profile Settings',
        },
      },
      {
        path: 'subscriptions',
        name: 'ProfileSubscriptions',
        component: ProfileSubscriptions,
        meta: {
          title: 'Your Subscriptions',
        },
      }]
  },

Upvotes: 1

Views: 1258

Answers (1)

chojnicki
chojnicki

Reputation: 3623

I had similiar issue that could be related to yours. In my case I'm using <Suspense> with async pages/components and only out transition. So I wanted to keep old component visible until new one is ready, and then perform transition. Problem was that while using unique key on <router-view> old page was disappearing right away, then there was blank space (or specified Suspense fallback), and finally transition to new page started. Without key transition it was working like I wanted, so no blank/fallback between pages.

Anyway, I described this so someone could google it.

Quick solution is here: https://github.com/vuejs/router/issues/1175

So if we use component from slot, key should be on that component and not router view.

So try this:

<div class="profile__main">
  <router-view v-slot="{ Component }">
    <Transition name="fade" mode="out-in" appear>
      <component :is="Component" :key="$route.fullPath"></component>
    </Transition>
  </router-view>
</div>

Upvotes: 1

Related Questions