vue

vue3 <Transition> 컴포넌트

deadeye 2023. 5. 18. 09:37

Vue에서 상태 변화에 대한 전환이나 애니메이션 작업을 돕기위해 존재하는 컴포넌트가 두가지 있는데

 

<Transtion>

- 요소나 컴포넌트가 DOM에 들어오거나 나갈 때 애니메이션을 적용하는 데 사용됩니다.

 

<TransitionGroup>

- v-for 리스트 내에 컴포넌트가 삽입 ,제거 및 이동 할 때 애니메이션을 적용하는데 사용됩니다.

 

<Transition> 컴포넌트

Transition은 내장 컴포넌트로써 별도로 import하지 않아도 어떤 곳에서든지 사용할 수 있습니다.

이 컴포넌트는 기본 슬롯을 ㄷ통해 전달된 요소나 컴포넌트에 대해 Enter, Leave 애니메이션을 적용하는데 사용 될 수 있습니다.

Enter , Leave는 다음 조건 중 하나에 의해 트리거 되는데

  • v-if, v-show 같은 조건부 렌더링
  • 특정 컴포넌트 요소를 통한 동적 컴포넌트 토글
  • 특별한 Key 속성 변경

해당 Transition 컴포넌트를 사용한 간단한 예시입니다.

 

<template>
  <div id="testTrans">
    <div class="trans_Btn">
      <button @click="show = !show">Toggle</button>
    </div>
	<div class="trans_result">
      <Transition>
        <p v-if="show">hello</p>
      </Transition>
    </div>
  </div>
</template>

// script
const show = ref(false);

// style
.v-enter-active,
.v-leave-active {
  transition: opacity 0.5s ease;
}

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

 

해당 코드에 대한 결과는

 

배경색등의 css는 맘대로 지정한것이니 무시

(다른건 안보고) Toggle버튼을 클릭하면 hello가 생기고 한번더 클릭하면 hello가 사라지는 걸 볼 수 있습니다.

그런데 이건 v-if기 때문에 당연한거고!

개발자 도구를 보면 아래와 같이 클래스가 생성이 되는데

 

Transition 태그는 6가지로 구성되어있고 각각의 역할이 존재하는데

        • v-enter-from: 진입 시작 상태입니다. 요소가 삽입되기 전에 추가되며, 요소가 삽입된 1프레임 후에 제거됩니다.
        • v-enter-active: 진입에 대한 활성 상태입니다. 전체 진입 단계 동안 적용됩니다. 요소가 삽입되기 전에 추가되며, 전환/애니메이션이 완료되면 제거됩니다.  클래스를 사용하여 진입 전환의 지속 시간, 지연 시간  이징 곡선을 정의할  있습니다.
        • v-enter-to: 진입 종료 상태입니다. 요소가 삽입된 1프레임 후에 추가됩니다 (v-enter-from 제거될 동일한 시간에). 전환/애니메이션이 완료되면 제거됩니다.
        • v-leave-from: 이탈 시작 상태입니다. 이탈 전환이 트리거될  즉시 추가되며, 1프레임 후에 제거됩니다.
        • v-leave-active: 이탈에 대한 활성 상태입니다. 전체 이탈 단계 동안 적용됩니다. 이탈 전환이 트리거될 즉시 추가되며, 전환/애니메이션이 완료되면 제거됩니다. 클래스를 사용하여 이탈 전환의 지속 시간, 지연 시간 이징 곡선을 정의할 있습니다.
        • v-leave-to: 이탈 종료 상태입니다. 이탈 전환이 트리거된  1프레임 후에 추가됩니다 (v-leave-from 제거될  동일한 시간에). 전환/애니메이션이 완료되면 제거됩니다.

출처  : https://vuejs.org/guide/built-ins/transition.html#css-based-transitions

 

Name

Transition을 여러번 사용할 수 있고 또 그떄마다 v-enter등을 사용할 수 없으니 구분할 수 있는 Name을 사용 할 수 있는데 사용법은 간단합니다.

css에서는 v대신 name을 넣는다고 보면 됩니다.

물론 하나만 사용할수 있는게 아니라 같은 name이 여러개 있어도 사용가능

추가적으로 :name으로 동적으로 사용도 가능

// css
// name을 사용하기전
.v-leave-to {
  opacity: 0;
}

// name 사용후
.slide-fade-leave-to {
	opacity: 0;
}

//template
// name사용 전
<Transition>
  <p v-if="show">hello</p>
</Transition>

// name사용
<Transition name="slide-fade>
  <p v-if="show">hello</p>
</Transition>

 

TansitionGroup 컴포넌트

list를 애니메이션을 적용하는데 도움을 주는 컴포넌트

 

Transition , TrasitionGroup 차이점

Transition TransitionGroup
   
   
   
   
   
   

 

예시

https://play.vuejs.org/#eNqtVE2P0zAQ/SujXNqgNmkPcIjaBbYCJKg4cSMcTDJNTB07+KNsVfW/M3aabNpyQltViT1vPPP8Zian6H3bJgeHURatTKF5ax9yyZtWaQuVYS3stGpg4peTXOayUNJYEJwea/ieS4ATNKbKYPKoXYGwRZzAeTYGPrNizxE2NZO30KZ2xR6+Kq25uTuGFrb81vrFyQo+On0kIJc/PCV8CmxL3DEnLJy8e8ksm8bdGkCjdVr2O4DfDvWRgtGN/JYC0SOkKVTTOotl1jv3hi3d+DngENILkey4sKinU26xiWH9AH6REN/Eqq36g3rDDE7jhMtCuBLN1NbcJIFEHN9RaNDWqjQDAyUfcac0fpA+CYoRCRSJsUeBiWpZwe2RSrK4w2rkVe2rdYG6LD5uH3EGpZI4iuurTdwDNBjpRJclg+UlhP914UnMZfIGm8kIKVEwciYivhoGLQlQ4hO8gkWyfD1yVHJDKgu0mAUmPXLuxRkYb5Ed8H8YL/7BeGx7Oa6hkLmk/yodBoo21BKtYBZpB7DikroKDvNGUeZ1HoVmyCNIO/ibZtJwy5X8pJVru9CWVeTpRB51+6wwhgw7Jgz2tnc/Q6/M0ZeWwKvmGZye0Wu78PIGexC6swdGxEnw/q6HOYUkt9DwMwhKxfS6GpY+KPHc45G8+6EYAV7reTjucf/uwUtSmvvTME1wDuISlVTwTqf0RiiyrtKR0tEs6r5l84b645dRkr5zoT8oXwBMHg2Tlke+jbwhj2prW5OlqZPtvkroYqnH3lK9nLgI46scnf8Cn22kBA==

 

 


Transition을 사용하지 않은 그외에 애니메이션 기법

  • 클래스 기반 애니메이션 : DOM에 들어오거나 나가지 않는 요소의 경우 CSS클래스를 동적 바인딩을 통해 애니메이션을 활용 할 수 있습니다.
    • 해당 예시에서 확인 할 수 있는 부분 
    • 더보기
      const data = ref(false)에서
      data.value = !data.value , data = !data의 차이점(스크립트에서의 변경과 템플릿에서 변경)
      data = !data는 반응성 업데이트를 하지 않으므로 값이 변경되더라도 템플릿이 재랜더링 되지 않음

      data.value = !data.value는 반응형 시스템에 적용되며 업데이트 값을 반영하도록 템플릿이 재렌더링됨
  • 상태 기반 애니메이션 : 특정값이 변함에 따라 적용되는 애니메이션

추가 예시 : https://play.vuejs.org/#eNqlVmtv2zYU/SsXboE6mC3bSdwVmpM9MAz9sAIdsA8b5gGhRUrWKpEESTl2DP/3HZKSbbkuUKBA4Ij3ce65D15pP/hZ62TTiEE6WNjMlNqRFa7Rj0tZ1loZR3sygmWu3IgRZarWjROcDpQbVdMbeL45WvKdZHWZ2VbXHZP/LGyWMlPSOloLxoV5L8pi7eiBZrdTr6uEo9L+alhRlLKAPGeVFZ2PdQzwD6CyTWk6oh1+6dBpM2g6isNgch4jWPeCHm4u2Xxkbg2QLrvh8IYeHmm/lARg1xhJTx+moyn9fnfr//nf1/tzzMMfr/dZsj1AnCW7Azhe6J+W8jwsfp2Q7qOypSuV/ELsaMt3Xp3saNxL48yA1Vp4DFg+ojA/0i2ldH/GPqAROcOkzZWpU3oKzxVzYui5wnPS4hz09gZsydc3Us4bidqCZWiD79FQ3ERMgagiydZMFoL/qZpsLSziX4r+mf4LRmgn9ZvsTBOEATjZBjDNCvHXSeiTj8K/wadHR8lv5ZLT8MSnhUFVA5PeyHxHw5YZutCyRW2C9alJLc+jya5n8VmXZsm865MP6hEugp61pevIRUOUDjVouX8hoWsXy8uPF5ThBvtRiGKQGXVPX3OdzozdTov0hGu1QdAR8cYwTzil76e4vrkpA/+Ubt+Fe+ydQzljhotJ3ETYQTg4UWs/qDgRLXi5aQtWMWsflgPuU2OrSiwHUfFTrRoruHqW0B5H9qh1fgyC+Ko6ONdqI6CNA9b3vK4KXo0OiLElfS8h+TVdcKsEC5B9bcgW+dpNcUx1BR09l9ytccASwmkdeoDj/C2OrRPctN9oqQ962nAwz8uqguzV3W/z2S9zOCwm3rILNkG07hmFPgaOGDD3/OiDWEygvWbY7jVESq3bVT6ti1UHkPeiqtQJontaTM46jWMAIJspLTgkybHRcaxXLPtUGNVIPs5UpUxKr/I8/yGo1HZs1wwj4N8T93pLs7f4McWKYdv5F4j/S2bzm2AeKpr6ra63QRCLium87yRouskrj7cuORcyCGtmcKfgCCtijVNBqttEUyxfJIN3UhA7sXVjVpUFFBnqIUwQ56jO2JYvuDUzED3JnlsOd9NpEGJQzNgPSwahVDKirpRBY8aG8bKxKb0LCLhByaqIVTqxYSurKrxhIhulUZrwWIkciPH5ZVxKLvw7toWJjccFT9o2XqL2cjy6z2IlGOe4/rFAp8aUL0HYUoeoF6t78/U72nUEXwvnRYqFuxX153VbqYpHYEy1nySM0GA0iF8q45ppfJUoia+eEG/ZKuxykHZbE6vl9AHj5bgHzmmbTiYZl4n9tNMYwYSLzaRn2O2xweF/7cIdbA==

 

watch를 통해서도 감시가능