<Transition> 컴포넌트


빌트인 컴포넌트.
등록하지 않고도 컴포넌트의 템플릿에서 사용할 수 있다.


  • 조건
    • v-if를 통한 조건부 렌더링
    • v-show를 통한 조건부 표시
    • 스페셜 엘리먼트 <component>를 통해 전환되는 동적 컴포넌트
    • key라는 특수한 속성 값 변경


<button @click="show = !show">토글</button>
<Transition>
  <p v-if="show">안녕</p>
</Transition>
.v-enter-active,
.v-leave-active {
  transition: opacity 0.5s ease;
}

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



CSS 기반 트랜지션




트랜지션 이름 지정

<Transition name="fade">
  ...
</Transition>
.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.5s ease;
}

.fade-enter-from,
.fade-leave-to {
  opacity: 0;
}
  • name prop을 통해 이름을 지정



CSS 애니메이션

<Transition name="bounce">
  <p v-if="show" style="text-align: center;">
    안녕! 여기에 탄력적인 텍스트가 있어요!
  </p>
</Transition>
.bounce-enter-active {
  animation: bounce-in 0.5s;
}
.bounce-leave-active {
  animation: bounce-in 0.5s reverse;
}
@keyframes bounce-in {
  0% {
    transform: scale(0);
  }
  50% {
    transform: scale(1.25);
  }
  100% {
    transform: scale(1);
  }
}


커스터마이징


  • <Transition> props에 커스텀 트랜지션 클래스를 정의하여 전달할 수 있다.
    • enter-from-class
    • enter-active-class
    • enter-to-class
    • leave-from-class
    • leave-active-class
    • leave-to-class
<!-- Animate.css가 페이지에 포함되어 있다고 가정합니다. -->
<Transition
  name="custom-classes"
  enter-active-class="animate__animated animate__tada"
  leave-active-class="animate__animated animate__bounceOutRight"
>
  <p v-if="show">안녕</p>
</Transition>


중첩된 트랜지션

<Transition name="nested">
  <div v-if="show" class="outer">
    <div class="inner">
      안녕
    </div>
  </div>
</Transition>
/* 중첩 엘리먼트를 대상으로 하는 규칙 */
.nested-enter-active .inner,
.nested-leave-active .inner {
  transition: all 0.3s ease-in-out;
}

.nested-enter-from .inner,
.nested-leave-to .inner {
  transform: translateX(30px);
  opacity: 0;
}


JavaScript 훅


<Transition> 컴포넌트의 이벤트를 수신하여 JavaScript로 트랜지션 프로세스에 연결

<Transition
  @before-enter="onBeforeEnter"
  @enter="onEnter"
  @after-enter="onAfterEnter"
  @enter-cancelled="onEnterCancelled"
  @before-leave="onBeforeLeave"
  @leave="onLeave"
  @after-leave="onAfterLeave"
  @leave-cancelled="onLeaveCancelled"
>
  <!-- ... -->
</Transition>
// 엘리먼트가 DOM에 삽입되기 전에 호출됩니다.
// 이것을 사용하여 엘리먼트의 "enter-from" 상태를 설정합니다.
function onBeforeEnter(el) {}

// 엘리먼트가 삽입되고 1 프레임 후 호출됩니다.
// 진입 애니메이션을 시작하는 데 사용합니다.
function onEnter(el, done) {
  // CSS와 함께 사용되는 경우, 선택적으로 
  // 트랜지션 종료를 나타내기 위해 done 콜백을 호출합니다.
  done()
}

// 진입 트랜지션이 완료되면 호출됩니다.
function onAfterEnter(el) {}

// 진입 트랜지션 취소가 완료되기 전 호출됩니다.
function onEnterCancelled(el) {}

// 진출 훅 전에 호출됩니다.
// 대부분의 경우 그냥 진출 훅을 사용해야 합니다.
function onBeforeLeave(el) {}

// 진출 트랜지션이 시작될 때 호출됩니다.
// 진출 애니메이션을 시작하는 데 사용합니다.
function onLeave(el, done) {
  // CSS와 함께 사용되는 경우, 선택적으로 
  // 트랜지션 종료를 나타내기 위해 done 콜백을 호출합니다.
  done()
}

// 진출 트랜지션이 완료되고,
// 엘리먼트가 DOM에서 제거된 후 호출됩니다.
function onAfterLeave(el) {}

// v-show 트랜지션에서만 사용 가능합니다.
function onLeaveCancelled(el) {}



트랜지션 모드


진출 애니메이션이 완료된 이후 수행하기를 원한다면

  • <Transition>에 mode prop을 전달하여 이 동작을 활성화
<Transition mode="out-in">
  ...
</Transition>
<Transition name="fade" mode="out-in">
  <component :is="activeComponent"></component>
</Transition>


동적 트랜지션


<Transition> name과 같은 prop도 동적일 수 있다.

<Transition :name="transitionName">
  <!-- ... -->
</Transition>


key 속성을 사용한 트렌지션


트렌지션을 발생시키기 위해 DOM 엘리먼트를 강제로 다시 렌더링해야 할 필요가 있다.

<script setup>
import { ref } from 'vue';
const count = ref(0);

setInterval(() => count.value++, 1000);
</script>

<template>
  <Transition>
    <span :key="count">{{ count }}</span>
  </Transition>
</template>
  • key 속성을 사용함으로써, Vue는 count가 변경될 때마다 새로운 span 엘리먼트를 생성하고 Transition 컴포넌트는 두 개의 다른 엘리먼트 사이에서 트렌지션을 할 수 있다.




트랜지션 그룹


<TransitionGroup>은 목록에서 렌더링되는 엘리먼트 또는 컴포넌트의 삽입, 제거 및 순서 변경을 애니메이션으로 만들기 위해 설계된 빌트인 컴포넌트


  • 기본적으로 래퍼 엘리먼트를 렌더링하지 않습니다. 그러나 tag prop으로 렌더링할 엘리먼트를 지정할 수 있다.
  • 트랜지션 모드는 더 이상 상호 배타적인 엘리먼트를 사용하지 않기 때문에 사용할 수 없다.
  • 내부 엘리먼트는 고유한 key 속성을 필수로 가져야 한다.
  • CSS 트랜지션 클래스는 그룹/컨테이너 자체가 아닌 목록의 개별 엘리먼트에 적용된다.


진입/진출 트랜지션

<TransitionGroup name="list" tag="ul">
  <li v-for="item in items" :key="item">
    {{ item }}
  </li>
</TransitionGroup>
.list-enter-active,
.list-leave-active {
  transition: all 0.5s ease;
}
.list-enter-from,
.list-leave-to {
  opacity: 0;
  transform: translateX(30px);
}


이동 트랜지션

.list-move, /* 움직이는 엘리먼트에 트랜지션 적용 */
.list-enter-active,
.list-leave-active {
  transition: all 0.5s ease;
}

.list-enter-from,
.list-leave-to {
  opacity: 0;
  transform: translateX(30px);
}

/* 이동 애니메이션을 올바르게 계산할 수 있도록
   레이아웃 흐름에서 나머지 항목을 꺼내기. */
.list-leave-active {
  position: absolute;
}


시차가 있는 목록 트랜지션

<TransitionGroup
  tag="ul"
  :css="false"
  @before-enter="onBeforeEnter"
  @enter="onEnter"
  @leave="onLeave"
>
  <li
    v-for="(item, index) in computedList"
    :key="item.msg"
    :data-index="index"
  >
    {{ item.msg }}
  </li>
</TransitionGroup>
function onEnter(el, done) {
  gsap.to(el, {
    opacity: 1,
    height: '1.6em',
    delay: el.dataset.index * 0.15,
    onComplete: done
  })
}
  • JavaScript 훅에서 data- 속성을 기반으로 딜레이를 사용하여 엘리먼트에 애니메이션을 적용





공식 메뉴얼: https://ko.vuejs.org/guide/built-ins/transition.html