Nuxt利用Vue的<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>
想要单独的为某个页面设置切换效果,可以这么设置
在definePageMate
中,设置一个pageTransition
属性,指定名称
<script setup lang="ts">
definePageMeta({
pageTransition: {
name: 'rotate'
}
})
</script>
然后在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>
由上面两个例子可以看出来,切换的样式命名格式为
[name]-enter-active
、[name]-enter-active
、[name]-enter-from
、[name]-leave-to
布局之间切换
同理,可以在nuxt.config.ts
中设置默认的布局切换效果
export default defineNuxtConfig({
app: {
layoutTransition: { name: 'layout', mode: 'out-in' }
},
})
同理,在app.vue
中,设置好css
<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>
命名则是layout加上后缀。
如果需要单独设置,同样的,在vue文件中,设置layoutTransition
,然后在app.vue
中设置css
<script setup lang="ts">
definePageMeta({
layout: 'orange',
layoutTransition: {
name: 'slide-in'
}
})
</script>
全局设置
可以在nuxt.config.ts
中同时设置pageTransition
和layoutTransition
export default defineNuxtConfig({
app: {
pageTransition: {
name: 'fade',
mode: 'out-in' // default
},
layoutTransition: {
name: 'slide',
mode: 'out-in' // default
}
}
})
在单独的页面中,也可以随时通过definePageMate进行覆盖设置。
禁止切换效果
在页面单独设置
<script setup lang="ts">
definePageMeta({
pageTransition: false,
layoutTransition: false
})
</script>
在配置文件中,全局设置
export default defineNuxtConfig({
app: {
pageTransition: false,
layoutTransition: false
}
})
JavaScript Hooks
可以通过hooks,自定义一些高级的切换效果。例如可以引入GSAP
这种三方库
<script setup lang="ts">
definePageMeta({
pageTransition: {
name: 'custom-flip',
mode: 'out-in',
onBeforeEnter: (el) => {
console.log('Before enter...')
},
onEnter: (el, done) => {},
onAfterEnter: (el) => {}
}
})
</script>
动态设置的切换效果
这个例子,最好到官网看看效果。文字描述不如视频来的直观
假设页面通过翻页器来进行切换。
那么想要为上一页设置一个从左到右的动画,为下一页设置一个从右到左的动画
那么我们可以通过内联的路由中间件,设置对应的pageTransition
<script setup lang="ts">
definePageMeta({
pageTransition: {
name: 'slide-right',
mode: 'out-in'
},
middleware (to, from) {
if (to.meta.pageTransition && typeof to.meta.pageTransition !== 'boolean')
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使用切换效果
当app.vue中使用<NuxtPage />
的时候,可以直接在它上面定义全局的切换效果
<template>
<div>
<NuxtLayout>
<NuxtPage :transition="{
name: 'bounce',
mode: 'out-in'
}" />
</NuxtLayout>
</div>
</template>
记住,这个转换不能被页面内的definePageMeta覆盖
视图切换api(View Transitions API)(实验性)
这个是利用Web Api来实现的,详情说明可以看MDN的说明
最终实现个什么效果呢?类似PPT中的平滑切换。保持相同的元素不动或者平移,不同的元素渐入渐出
首先,开启这个实验性的功能
nuxt.config.ts
export default defineNuxtConfig({
experimental: {
viewTransition: true
}
})
viewTransition
可以设置为true
,false
,'alway'
。当设置true
的时候,应用会去检查浏览器的设置是否为prefers-reduced-motion: reduce
,如果是则应用效果。如果是alway,则不会去匹配这个效果。
可以在页面内覆盖这个值
(如果不在nuxt.config.ts开启这个api,只是在这里设置,是无法开启的)
<script setup lang="ts">
definePageMeta({
viewTransition: false
})
</script>
如果你同时使用基于vue的<Transition>
实现的pageTransition
和layoutTransition
来实现和View Transitions API
相同的效果。当浏览器支持这个原生的View Transitions API的时候,你可能想要禁用重复的Vue的transition仙姑过。你可以通过创建以下的disable-vue-trasitions.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的setup中执行数据获取的操作,你可能需要重新考虑是否使用这个功能。(按照设计,View Transitions 在进行过程中会完全冻结 DOM 更新。)我们正在研究将 View Transition 限制在
<Suspense>
解析前的最后一刻,但在过渡期间,如果您的情况符合上述描述,您可能需要仔细考虑是否采用此特性。
总结,这个api不太适用于企业后台的展示。