Nuxt利用了Vue的<Transition>
组件,来处理页面和布局之间的跳转动画。
在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>
如果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使用才会生效的。
如上面介绍,页面动画和布局动画,都可以在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钩子为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>
利用页面级中间件,可以为页面动画动态地设置不同的名称。
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>
组件设置transition
属性以应用过渡动画。这样设置的动画,无法后续被definePageMeta
覆盖。
app.vue
<template>
<div>
<NuxtLayout>
<NuxtPage :transition="{
name: 'bounce',
mode: 'out-in'
}" />
</NuxtLayout>
</div>
</template>
在支持View Transition API的浏览器上(比如Chrome 111及以上),Nuxt从3.4开始支持一种更简单的设置页面过渡动画的方法。只需要在nuxt.config.ts
中按如下配置:
export default defineNuxtConfig({
experimental: {
viewTransition: true
}
})