Skip to content

路由动画

INFO

Nuxt3 利用 Vue<Transition>组件在页面和布局之间应用过度效果

页面

你可以启用页面过度来为所有页面应用页面动画

使用(通用)

  • nuxt.config.ts
js
// nuxt.config.ts
export default defineNuxtConfig({
  app: {
    pageTransition: { name: "page", mode: "out-in" },
  },
});

如果你同时更改布局和页面,这里设置的页面过渡效果不会运行,相反你应该设置布局过度效果

  • app.vue
html
<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
html
<template>
  <div>
    <h1>首页</h1>
    <NuxtLink to="/about">关于页面</NuxtLink>
  </div>
</template>
  • pages/about.vue
html
<template>
  <div>
    <h1>关于页面</h1>
    <NuxtLink to="/">首页</NuxtLink>
  </div>
</template>

单独

如果要为页面设置不同的页面动画,请在页面的definePageMeta中设置pageTransition

  • pages/about.vue
html
<script setup lang="ts">
  definePageMeta({
    pageTransition: {
      name: "rotate",
    },
  });
</script>
  • app.vue
html
<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>

布局

你可以启动布局动画来为所有的布局添加动画

使用(通用)

  • nuxt.config.ts
js
export default defineNuxtConfig({
  app: {
    layoutTransition: { name: "layout", mode: "out-in" },
  },
});

要开始在页面和布局之间添加动画效果,请在app.vue 中添加 css

  • app.vue
html
<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>

单独使用

pageTransition类似,你可以使用definePageMeta将自定义的layoutTransition应用到页面组件

html
<script setup lang="ts">
  definePageMeta({
    layout: "orange",
    layoutTransition: {
      name: "rotate",
    },
  });
</script>
  • app.vue
js
<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>

禁用动画

可以为特定的路由禁用pageTransitionlayoutTransition

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

或在nuxt.config中全局禁用:

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

自定义动画钩子函数

对于高级用例,你可以使用 JavaScript 钩子为 Nuxt 页面创建高度动态和自定义的过渡效果。

这种方式非常适合使用 GSAPJavaScript 动画库。

html
<script setup lang="ts">
  definePageMeta({
    pageTransition: {
      name: "custom-flip",
      mode: "out-in",
      onBeforeEnter: (el) => {
        console.log("进入之前...");
      },
      onEnter: (el, done) => {},
      onAfterEnter: (el) => {},
    },
  });
</script>

动态过度

要使用条件逻辑应用动态过渡效果,你可以利用内联 middleware 将不同的过渡名称分配给 to.meta.pageTransition

  • pages/[id].vue
html
<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>

页面现在在前往下一个 id 时应用 slide-left 过渡效果,在前一个 id 时应用 slide-right 过渡效果: