1. Page Transitions(页面跳转动画)
    2. Layout transitions(布局动画)
    3. Global settings(全局设置)
    4. 禁用跳转动画
    5. Javascript Hooks(JS勾子)
    6. Dynamic Transitions(动态的过渡动画)
    7. NuxtPage组件动画
    8. View Transitions API (experimental)

Nuxt利用了Vue的<Transition>组件,来处理页面和布局之间的跳转动画。

Page Transitions(页面跳转动画)

nuxt.config.ts中定义全局的页面动画:

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

然后,还需要在入口文件app.vue中设置过渡动画css:

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>

效果如下: Video

如果仅仅给某一个特定的页面设置动画,而不使用全局,则可以在页面中使用definePageMeta函数。

pages/about.vue

<script setup lang="ts">
definePageMeta({
  pageTransition: {
    name: 'rotate'
  }
})
</script>

修改pages/app.vue中的css

<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>

Layout transitions(布局动画)

如果Nuxt应用中有多个布局(layouts/目录下),那么不同布局进行切换的时候,页面动画将不会起作用,要改用布局动画。

nuxt.config.ts中设置布局动画:

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

在单独的页面中设置布局和动画: pages/about.vue

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

记得要像页面动画那样,配合css使用才会生效的。

Global settings(全局设置)

如上面介绍,页面动画和布局动画,都可以在nuxt.config.ts中全局设置。

export default defineNuxtConfig({
  app: {
    pageTransition: {
      name: 'fade',
      mode: 'out-in' // default
    },
    layoutTransition: {
      name: 'slide',
      mode: 'out-in' // default
    }
  }
})

在配置了全局动画的情况下,如果某个页面/布局想覆盖全局而使用不同的动画,则需要在页面里面使用definePageMeta

pages/about.vue

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

禁用跳转动画

页面级禁用:

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

nuxt.config.ts中全局禁用:

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

Javascript Hooks(JS勾子)

一些高级复杂的场景,则可以使用JavaScript钩子为Nuxt页面创建高度动态和自定义的转换效果。 这种方法非常适合使用GSAP或Tween.js等JavaScript动画库的场景。

<script setup lang="ts">
definePageMeta({
  pageTransition: {
    name: 'custom-flip',
    mode: 'out-in',
    onBeforeEnter: (el) => {
      console.log('Before enter...')
    },
    onEnter: (el, done) => {},
    onAfterEnter: (el) => {}
  }
})
</script>

Dynamic Transitions(动态的过渡动画)

利用页面级中间件,可以为页面动画动态地设置不同的名称。

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>

NuxtPage组件动画

可以为<NuxtPage>组件设置transition属性以应用过渡动画。这样设置的动画,无法后续被definePageMeta覆盖。

app.vue

<template>
  <div>
    <NuxtLayout>
      <NuxtPage :transition="{
        name: 'bounce',
        mode: 'out-in'
      }" />
    </NuxtLayout>
  </div>
</template>

View Transitions API (experimental)

在支持View Transition API的浏览器上(比如Chrome 111及以上),Nuxt从3.4开始支持一种更简单的设置页面过渡动画的方法。只需要在nuxt.config.ts中按如下配置:

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

参考: https://nuxt.com/docs/getting-started/transitions