Skip to content

전환

라우트 컴포넌트에 전환 효과를 사용하고 내비게이션에 애니메이션을 적용하려면 <RouterView> 슬롯을 사용해야 합니다:

template
<router-view v-slot="{ Component }">
  <transition name="fade">
    <component :is="Component" />
  </transition>
</router-view>

모든 transition API는 여기에서도 동일하게 동작합니다.

라우트별 전환

위 사용법은 모든 라우트에 같은 전환 효과를 적용합니다. 각 라우트 컴포넌트에 서로 다른 전환 효과를 주고 싶다면 meta 필드<transition>의 동적 name을 결합할 수 있습니다:

js
const routes = [
  {
    path: '/custom-transition',
    component: PanelLeft,
    meta: { transition: 'slide-left' },
  },
  {
    path: '/other-transition',
    component: PanelRight,
    meta: { transition: 'slide-right' },
  },
]
template
<router-view v-slot="{ Component, route }">
  <!-- 사용자 정의 전환을 사용하거나 `fade`로 대체합니다 -->
  <transition :name="route.meta.transition || 'fade'">
    <component :is="Component" />
  </transition>
</router-view>

라우트 기반 동적 전환

대상 라우트와 현재 라우트의 관계를 기준으로 사용할 전환을 동적으로 결정할 수도 있습니다. 방금 전 예제와 매우 비슷한 코드를 사용하면:

template
<!-- 동적 전환 이름을 사용합니다 -->
<router-view v-slot="{ Component, route }">
  <transition :name="route.meta.transition">
    <component :is="Component" />
  </transition>
</router-view>

라우트 깊이를 기준으로 meta 필드에 정보를 동적으로 추가하기 위해 내비게이션 후 훅을 추가할 수 있습니다

js
router.afterEach((to, from) => {
  const toDepth = to.path.split('/').length
  const fromDepth = from.path.split('/').length
  to.meta.transition = toDepth < fromDepth ? 'slide-right' : 'slide-left'
})

재사용되는 뷰 사이에서 전환 강제하기

Vue는 비슷해 보이는 컴포넌트를 자동으로 재사용하여 전환을 생략할 수 있습니다. 다행히 key 속성을 추가해 전환을 강제할 수 있습니다. 이렇게 하면 같은 라우트에 머무르면서 params만 바뀌는 경우에도 전환을 트리거할 수 있습니다:

template
<router-view v-slot="{ Component, route }">
  <transition name="fade">
    <component :is="Component" :key="route.path" />
  </transition>
</router-view>

초기 내비게이션과 전환

보통 Vue의 <Transition>appear prop을 추가하지 않으면 enter 애니메이션을 무시합니다. 하지만 <RouterView>와 함께 사용할 때는 appear prop을 설정하지 않아도 전환이 항상 적용되는 것을 볼 수 있습니다. 이는 Vue Router에서 내비게이션이 비동기이기 때문에, 초기 내비게이션이 끝나기 전에 Vue 애플리케이션이 한 번 렌더링되기 때문입니다. 이를 다루는 방법은 여러 가지가 있습니다. 가장 쉬운 방법은 isReady를 사용해 초기 내비게이션을 기다린 뒤 앱을 마운트하는 것입니다:

ts
const app = createApp(App)
app.use(router)

// 초기 내비게이션이 준비된 뒤 마운트합니다
await router.isReady()
app.mount('#app')

모두를 위한 문서 한글화