티스토리 뷰
요즘 출시되는 웹 애플리케이션에서는 페이지 전환시 애니메이션 동작이 거의 필수로 들어가있다. 이러한 애니메이션은 꼭 네이티브가 아니라 vue로 만든 SPA에서 지정할 수 있다. vue에서는 내장 애니메이션 컴포넌트인 <transition>
을 활용하면 된다.
transition을 사용하는 방법은 공식문서나 다른 분들이 올려놓은 블로그에 이미 잘 정리되어 있으므로 이번 글에서는 실질적으로 페이지 이동할 때마다 transition이 일어나게 하는 방법을 소개하겠다. 기존의 공식문서에서는 URL을 split('/')
하여 몇 개의 부분으로 나뉘는 지를 기준으로 삼아서 toDepth
와 fromDepth
값을 비교하여 애니메이션 방식을 정하고 있다. 이 방식도 좋은 방법이기는 하지만, 라우팅 정책을 엄격하게 세워야하기 때문에 내가 하기에는 다소 불편하다고 판단하여 방법을 바꾸기로 했다.
일단 모든 페이지에 대해서 transition을 넣을 것이므로 단순하게 생각해보자면 <router-view />
을<trainsition>
감싸는 형태를 생각해볼 수 있다.
// App.vue
<transition name="transitionName">
<router-view />
</transition>
다만 공식문서에서는 router에 transition을 넣는 경우, v-slot
을 활용하여 넣는 방식을 안내하고 있으므로,
// App.vue
<router-view v-slot="{ Component }">
<transition :name="transitionName">
<component :is="Component" />
</transition>
</router-view>
이 방식이 더 적합한 방식이다. v-slot
을 활용할 경우 <component>
태그 안에 들어갈 컴포넌트를 동적으로 명시할 수 있으므로 이 방식을 소개한 것으로 보인다. 여기까지 했으면 이제 transitionName
을 상황에 따라 지정해주면 된다. 이 글에서 소개한 transition은 특정 페이지로 이동 시 화면이 오른쪽에서 덮이는 slide-right
와 뒤로 가기시 화면이 왼쪽에서 덮이는 slide-left
를 소개하려고 한다.
페이지 이동하는 경우를 감지하기 위해서는 vue-router의 beforeEach
를 활용하는 경우도 있지만, App.vue
단에서도 watch
를 사용하여 인자로 route.name
을 넣으면 감지할 수 있다. 여기서 신경써야 하는 부분은 router를 통한 페이지 이동이든, 뒤로가기를 통한 이동이든 모두 watch
에 감지되기 때문에 사용자의 행동이 둘 중에서 어떤 것인지 알 수가 없다는 점이다. 그래서 우리는 사용자가 뒤로가기를 눌렀을 때만 발동되는 트리거가 무엇인지 알아야 한다. 그 트리거는 바로 윈도우 이벤트 중 하나인 popstate
이다. 따라서 이벤트가 발동되면 isGoBack
이라는 변수를 true
로 세팅해두고 watch
안에서는 이 값에 따라서 사용자가 뒤로가기를 눌렀는지, 아니면 router를 통한 이동이었는지를 판단할 수 있게 된다.
// App.vue - script
setup(){
let transitionName = ref('none');
let isGoBack = false;
window.addEventlistener('popstate',()=>{
isGoBack = true;
})
watch(()=>route.name,
(to,from)=>{
// 우선 효과 없는 상태로 초기화
transitionName.value = 'none';
if(isGoBack){
// 뒤로가기
transitionName.value = 'slide-left';
isGoBack = false;
} else {
// 페이지 이동
if(from === undefined) return; // 새로고침인 경우
transitionName.value = 'slide-right';
}
})
return{
transitionName,
}
}
// App.vue - style
/* 슬라이드 START */
.none-enter-active,
.none-leave-active {
display: none;
}
.none-enter-from {
display: none;
}
.none-leave-to {
display: none;
}
/* slide right */
.slide-right-enter-active,
.slide-right-leave-active {
transition: transform 0.2s ease;
}
.slide-right-enter-from {
transform: translateX(100%);
}
.slide-right-leave-to {
transform: translateX(-100%);
}
/* slide left */
.slide-left-enter-active,
.slide-left-leave-active {
transition: transform 0.2s ease;
}
.slide-left-enter-from {
transform: translateX(-100%);
}
.slide-left-leave-to {
transform: translateX(100%);
}
/* 슬라이드 END */
'Dev' 카테고리의 다른 글
vue3 modal 모달 열고 닫기 (0) | 2023.03.09 |
---|---|
vue3 modal transition(모달 트랜지션) (0) | 2023.03.09 |
vue-chart-3에서 비동기 통신 이후 데이터 그리기 (0) | 2023.03.09 |
vue 에서 스크롤 위치 저장 (0) | 2023.03.09 |
프로젝트 회고 (0) | 2023.02.18 |