9. Transitions

<!--
pages/about.vue
-->

<script setup lang="ts">
definePageMeta({
  layout: 'orange'
})
</script>

<template>
  <div>
    <h1>About page</h1>
    <NuxtLink to="/">Home page</NuxtLink>
  </div>
</template>

Transition을 이용하여 페이지와 레이아웃간 트랜지션을 적용할 수 있다.

 

페이지 트랜지션 (Transition)

페이지 트랜지션 을 활성화하여 모든 페이지에 자동 트랜지션 을 적용할 수 있다.

// nuxt.config.ts

export default defineNuxtConfig({
  app: {
    pageTransition: { name: 'page', mode: 'out-in' }
  },
})

힌트) 페이지뿐만 아니라 레이아웃도 변경하는 경우 여기에서 설정한 페이지 트랜지션 이 실행되지 않는다. 대신 레이아웃 트랜지션 을 설정해야 한다.

<!--
app.vue
-->

<template>
  <NuxtPage />
</template>

<style>
.page-enter-active,
.page-leave-active {
  transition: all 0.4s;
}
.page-enter-from,
.page-leave-to {
  opacity: 0;
  filter: blur(1rem);
}
</style>
<!--
pages/index.vue
-->

<template>
  <div>
    <h1>Home page</h1>
    <NuxtLink to="/about">About page</NuxtLink>
  </div>
</template>
<!--
pages/about.vue
-->

<template>
  <div>
    <h1>Home page</h1>
    <NuxtLink to="/about">About page</NuxtLink>
  </div>
</template>

페이지간 탐색 결과 동영상

 

페이지에 대해 다른 트랜지션을 설정하려면 페이지 definePageMeta 의 pageTransition 키를 설정해야한다.

<!--
pages/about.vue
-->
<script setup lang="ts">
definePageMeta({
  pageTransition: {
    name: 'rotate'
  }
})
</script>


<!--
app.vue
-->
<template>
  <NuxtPage />
</template>

<style>
/* ... */
.rotate-enter-active,
.rotate-leave-active {
  transition: all 0.4s;
}
.rotate-enter-from,
.rotate-leave-to {
  opacity: 0;
  transform: rotate3d(1, 1, 1, 15deg);
}
</style>

페이지로 이동하면 3D 회전 효과가 추가된다.

동영상

 

레이아웃 트랜지션

레이아웃 트랜지션을 활성화하여 모든 레이아웃에 자동 트랜지션을 적용할 수 있다.

// nuxt.config.ts

export default defineNuxtConfig({
  app: {
    layoutTransition: { name: 'layout', mode: 'out-in' }
  },
})

페이지와 레이아웃 사이에 트랜지션을 추가하려면 app.vue 에 다음  CSS를 추가한다.

<!--
app.vue
-->

<template>
  <NuxtLayout>
    <NuxtPage />
  </NuxtLayout>
</template>

<style>
.layout-enter-active,
.layout-leave-active {
  transition: all 0.4s;
}
.layout-enter-from,
.layout-leave-to {
  filter: grayscale(1);
}
</style>
<!--
layouts/default.vue
-->

<template>
  <div>
    <pre>default layout</pre>
    <slot />
  </div>
</template>

<style scoped>
div {
  background-color: lightgreen;
}
</style>
<!--
layouts/orange.vue
-->

<template>
  <div>
    <pre>orange layout</pre>
    <slot />
  </div>
</template>

<style scoped>
div {
  background-color: #eebb90;
  padding: 20px;
  height: 100vh;
}
</style>
<!--
pages/index.vue
-->

<template>
  <div>
    <h1>Home page</h1>
    <NuxtLink to="/about">About page</NuxtLink>
  </div>
</template>

위 소스를 작성해서 페이지간을 이동하면 아래와 같다.

동영상

 

pageTransition 과 유사하게 definePageMeta를 사용하여 사용자 정의 layoutTransition 을 페이지에 추가할 수 있다.

<script setup lang="ts">
definePageMeta({
  layout: 'orange',
  layoutTransition: {
    name: 'slide-in'
  }
})
</script>

 

전역설정

nuxt.config 를 사용하여 이러한 기본 트랜지션 이름을 전체적으로 사용자 정의할 수 있다.

 

pageTransition 및 layoutTransition키 모두 사용자 정의 CSS 트랜지션 시, name 및 mode 등 트랜지션에 필요한 속성값을 전달할 수 있는 JSON 직렬화 가능한 속성값(TransitionProps)이 허용된다.

<!--
nuxt.config.ts
-->

export default defineNuxtConfig({
  app: {
    pageTransition: {
      name: 'fade',
      mode: 'out-in' // default
    },
    layoutTransition: {
      name: 'slide',
      mode: 'out-in' // default
    }
  }
})
name 속성을 변경하는 경 CSS 클래스 이름도 바꿔야 한다.

 

전역 트랜지션 속성을 재정의하려면 단일 Nuxt 페이지에 대한 페이지 또는 레이아웃 트랜지션을 정의하고 nuxt.config파일에 전역적으로 정의된 모든 페이지 또는 레이아웃 트랜지션을 재정의하는데 definePageMeta 를사용한다.

<!--
pages/some-page.vue
-->

<script setup lang="ts">
definePageMeta({
  pageTransition: {
    name: 'bounce',
    mode: 'out-in' // default
  }
})
</script>

특정 라우팅 경로 상에서 pageTransition, layoutTransition 을 사용하지 않을 수도 있다.

<!--
pages/some-page.vue
-->

<script setup lang="ts">
definePageMeta({
  pageTransition: false,
  layoutTransition: false
})
</script>

이를 전역적으로 적용하기 위해서는 nuxt.config 에서 설정한다.

// nuxt.config.ts

defineNuxtConfig({
  app: {
    pageTransition: false,
    layoutTransition: false
  }
})

 

자바스크립트 후크

고급 사용 사례의 경우 JavaScript 후크를 사용하여 Nuxt 페이지에 대한 매우 동적인 사용자 정의 트랜지션을 생성할 수 있다.


이 방법은 GSAP 와 같은 JavaScript 애니메이션 라이브러리에 대한 완벽한 사용 사례를 제공한다.

<!--
pages/some-page.vue
-->

<script setup lang="ts">
definePageMeta({
  pageTransition: {
    name: 'custom-flip',
    mode: 'out-in',
    onBeforeEnter: (el) => {
      console.log('Before enter...')
    },
    onEnter: (el, done) => {},
    onAfterEnter: (el) => {}
  }
})
</script>
트랜지션 컴포넌트에서 자바스크립트 후크를 사용하기 위한 방법은 여기에서 확인하자.

 

동적 트랜지션

조건을 사용하여 동적 트랜지션을 적용하려면 인라인 미들웨어를 활용하여 to.meta.pageTransition 에 다른 트랜지션 이름을 할당 할 수 있다.

<!--
pages/[id].vue
-->

<script setup lang="ts">
definePageMeta({
  pageTransition: {
    name: 'slide-right',
    mode: 'out-in'
  },
  middleware (to, from) {
    to.meta.pageTransition.name = +to.params.id > +from.params.id ? 'slide-left' : 'slide-right'
  }
})
</script>

<template>
  <h1>#{{ $route.params.id }}</h1>
</template>

<style>
.slide-left-enter-active,
.slide-left-leave-active,
.slide-right-enter-active,
.slide-right-leave-active {
  transition: all 0.2s;
}
.slide-left-enter-from {
  opacity: 0;
  transform: translate(50px, 0);
}
.slide-left-leave-to {
  opacity: 0;
  transform: translate(-50px, 0);
}
.slide-right-enter-from {
  opacity: 0;
  transform: translate(-50px, 0);
}
.slide-right-leave-to {
  opacity: 0;
  transform: translate(50px, 0);
}
</style>
<!--
layouts/default.vue
-->

<script setup lang="ts">
const route = useRoute()
const id = computed(() => Number(route.params.id || 1))
const prev = computed(() => '/' + (id.value - 1))
const next = computed(() => '/' + (id.value + 1))
</script>

<template>
  <div>
    <slot />
    <div v-if="$route.params.id">
      <NuxtLink :to="prev">⬅️</NuxtLink> |
      <NuxtLink :to="next">➡️</NuxtLink>
    </div>
  </div>
</template>

이제 페이지는다음 ID(slide-left) 와 이전 ID(slide-right) 로 이동할 때 트랜지션을 적용할 수 있다.

동영상

 

NuxtPage를 사용한 트랜지션

app.vue 에서  <NuxtPage /> 가 사용되는 경우 트랜지션 속성값은 전역 트랜지션을 활성화하기 위해 컴포넌트 속성값으로 직접 전달될 수 있다.

<!--
app.vue
-->

<template>
  <div>
    <NuxtLayout>
      <NuxtPage :transition="{
        name: 'bounce',
        mode: 'out-in'
      }" />
    </NuxtLayout>
  </div>
</template>
개별 페이지에서는 definePageMeta 를 이용하여 위 페이지 트랜지을 재정의할 수 없다는 점을 기억하자.

 

View Transition API(실험용)

Nuxt는 View Transitions API 의 실험적 구현을 ​​제공한다 ( MDN 참조 ). 이는 무엇보다도 서로 다른 페이지의 관련 없는 요소 사이를 트랜지션할 수 있는 기능을 갖춘 기본 브라우저 트랜지션 을 구현하는 흥미롭고 새로운 방법이다.
Nuxt 통합은 활발하게 개발 중이지만 nuxt.config.ts 구성 파일의 옵션을 사용하여 experimental.viewTransition 을 활성화할 수 있다.

// nuxt.config.ts

export default defineNuxtConfig({
  experimental: {
    viewTransition: true
  }
})

새로운 View Transitions API와 동일한 결과를 얻기 위해 pageTransition 및 ayoutTransition (위 참조) 와 같은 Vue 트랜지션을 사용하는 경우, 사용자의 브라우저가 최신 기본 웹 API를 지원하면 Vue 트랜지션을 비활성화 할 수 있다. 다음 내용으로 ~/middleware/disable-vue-transitions.global.ts 파일을 생성하여 이를 수행할 수 있다.

export default defineNuxtRouteMiddleware(to => {
  if (import.meta.server || !document.startViewTransition) { return }

  // Disable built-in Vue transitions
  to.meta.pageTransition = false
  to.meta.layoutTransition = false
})

 

알려진 문제

  • 업스트림 Vue 버그( https://github.com/vuejs/core/issues/5513 )로 인해 중첩된 페이지/레이아웃/비동기 구성 요소에서 보기 트랜지션이 예상대로 작동하지 않을 수 있다 . 이 패턴을 사용하는 경우 이 실험적 기능 채택을 연기하거나 직접 구현해야 할 수도 있다.
  • page setup 기능 내에서 데이터 가져오기를 수행하는 경우 잠시 동안 이 기능 사용을 재고해 볼 수 있다. (설계상, View Transition 은 DOM 업데이트가 진행되는 동안 완전히 동결된다.) 우리는 View Transition 을 <Suspense>을 통해 해결하기  전까지 제한하려고 한다 . 그전에는 이 기능을 채택할지 여부를 신중하게 고려할 수 있다.

'Nuxt 공식문서 번역 > 개요' 카테고리의 다른 글

11. 상태 관리  (0) 2023.12.11
10. 데이터 가져오기(Data fetching)  (0) 2023.12.11
8. SEO 와 Meta  (0) 2023.12.10
7. 라우팅  (0) 2023.12.10
6. Styling  (1) 2023.12.10
  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유