관리 메뉴

즐겁게, 코드

Vue 3에서 페이지 전환 애니메이션 추가하기 본문

🎨 프론트엔드/Vue.js

Vue 3에서 페이지 전환 애니메이션 추가하기

Chamming2 2023. 12. 24. 15:19

리액트와 비교했을 때 뷰의 장점 중 하나는 유용한 빌트인 컴포넌트를 제공한다는 점이라 생각한다.

https://vuejs.org/guide/built-ins/transition.html

이 중 <Transition> 컴포넌트는 정말 유용하게 사용하고 있는 중인데, 페이지 전환 시에도 트랜지션 효과를 줄 수 있다고 한다.

<template>
  <div>
    <router-link to="/">Home</router-link>
    <router-link to="/about">About</router-link>
    <router-link to="/contact">Contact</router-link>
  </div>
  <router-view />
</template>

nuxt가 아닌 vue-router로 라우터를 구성하면 위와 같이 router-view 컴포넌트를 사용한다.

<template>
  <div>
    <router-link to="/">Home</router-link>
    <router-link to="/about">About</router-link>
    <router-link to="/contact">Contact</router-link>
  </div>
  <Transition name="트랜지션 이름">
    <router-view />
  </Transition>
</template>

그리고 <Transition> 으로 <router-view> 를 감싸면 애니메이션이 잘 적용된 것처럼 보이나, 콘솔에 경고가 출력된다.

<template>
  <div>
    <router-link to="/">Home</router-link>
    <router-link to="/about">About</router-link>
    <router-link to="/contact">Contact</router-link>
  </div>
  <router-view v-slot="{ Component }">
    <component :is="Component" />
  </router-view>
</template>

대신 router-view는 "Component" 라는 named slot을 expose하는데, expose된 Component 슬롯을 동적으로 렌더한다. 

(※ 여기서 Component 는 현재 경로에서 렌더링되어야 하는 컴포넌트다.)

<template>
  <div>
    <router-link to="/">Home</router-link>
    <router-link to="/about">About</router-link>
    <router-link to="/contact">Contact</router-link>
  </div>
  <router-view v-slot="{ Component }">
    <Transition name="route" mode="out-in">
      <component :is="Component" />
    </Transition>
  </router-view>
</template>

이제 동적으로 렌더한 <component /> 컴포넌트에 <Transition> 컴포넌트를 감싸면 경고가 사라지고, 멋진 라우팅 네비게이션이 적용된 것을 확인할 수 있다.

번외. 그런데 왜 경고가 출력됐던 것일까?

먼저 GPT의 답변은 <router-view> 는 functional component 이며 <Transition> 은 stateful component 이므로 둘의 동작이 달라 부작용이 생길 수 있다는 내용이다.

 

vue-router의 <router-view> 는 다음과 같이 구현되어 있다.

https://github.dev/vuejs/vue-router/blob/dev/src/components/view.js

 

그리고 Vue의 <Transition> 유틸 컴포넌트는 다음과 같이 구현되어 있다.

Transition 컴포넌트는 BaseTransition 컴포넌트를 확장해 인스턴스를 생성한다.
https://github.dev/vuejs/core/blob/main/packages/runtime-dom/src/components/Transition.ts

 

BaseTransition을 살펴보면 setup API를 활용해 stateful하게 동작하고 있는데, <router-view> 은 setup 없이 가상 DOM을 구성하는데 사용하는 VNode만을 리턴하고 있다.

<router-view> 는 functional component고 <Transition>은 stateful component를 children으로 받기를 기대하지만, Composition API의 도움으로 functional과 stateful이 함께 사용될 수 있는 것이다.

(= 즉 원래대로면 Error 가 되었어야 하는 부분을 Warning 으로 누그러뜨릴 수 있었던 것 같다.)

 

추가로 알아볼 키워드

  • h (hyperscript) 함수
  • Composition API
  • VNode
반응형
Comments
소소한 팁 : 광고를 눌러주시면, 제가 뮤지컬을 마음껏 보러다닐 수 있어요!
와!! 바로 눌러야겠네요! 😆