过渡
<Transition>
组件在页面和布局之间应用过渡效果。页面过渡效果
¥Page Transitions
你可以启用页面转换,为所有 pages 应用自动转换。
¥You can enable page transitions to apply an automatic transition for all your pages.
export default defineNuxtConfig({
app: {
pageTransition: { name: 'page', mode: 'out-in' }
},
})
要在页面之间添加过渡效果,请将以下 CSS 添加到 app.vue
中:
¥To start adding transition between your pages, add the following CSS to your 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>
<template>
<div>
<h1>Home page</h1>
<NuxtLink to="/about">About page</NuxtLink>
</div>
</template>
<template>
<div>
<h1>About page</h1>
<NuxtLink to="/">Home page</NuxtLink>
</div>
</template>
在页面之间导航时,此方法会产生以下结果:
¥This produces the following result when navigating between pages:
要为页面设置不同的过渡效果,请在页面的 definePageMeta
中设置 pageTransition
键:
¥To set a different transition for a page, set the pageTransition
key in definePageMeta
of the page:
<script setup lang="ts">
definePageMeta({
pageTransition: {
name: 'rotate'
}
})
</script>
<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 旋转效果:
¥Moving to the about page will add the 3d rotation effect:
布局过渡
¥Layout Transitions
你可以启用布局转换,为所有 layouts 应用自动转换。
¥You can enable layout transitions to apply an automatic transition for all your layouts.
export default defineNuxtConfig({
app: {
layoutTransition: { name: 'layout', mode: 'out-in' }
},
})
要在页面和布局之间添加过渡效果,请将以下 CSS 添加到 app.vue
中:
¥To start adding transition between your pages and layouts, add the following CSS to your 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>
<template>
<div>
<pre>default layout</pre>
<slot />
</div>
</template>
<style scoped>
div {
background-color: lightgreen;
}
</style>
<template>
<div>
<pre>orange layout</pre>
<slot />
</div>
</template>
<style scoped>
div {
background-color: #eebb90;
padding: 20px;
height: 100vh;
}
</style>
<template>
<div>
<h1>Home page</h1>
<NuxtLink to="/about">About page</NuxtLink>
</div>
</template>
<script setup lang="ts">
definePageMeta({
layout: 'orange'
})
</script>
<template>
<div>
<h1>About page</h1>
<NuxtLink to="/">Home page</NuxtLink>
</div>
</template>
在页面之间导航时,此方法会产生以下结果:
¥This produces the following result when navigating between pages:
与 pageTransition
类似,你可以使用 definePageMeta
将自定义 layoutTransition
应用于页面组件:
¥Similar to pageTransition
, you can apply a custom layoutTransition
to the page component using definePageMeta
:
<script setup lang="ts">
definePageMeta({
layout: 'orange',
layoutTransition: {
name: 'slide-in'
}
})
</script>
全局设置
¥Global Settings
你可以使用 nuxt.config
全局自定义这些默认的过渡名称。
¥You can customize these default transition names globally using nuxt.config
.
pageTransition
和 layoutTransition
的键都接受 TransitionProps
作为 JSON 可序列化值,你可以在其中传递自定义 CSS 过渡的 name
、mode
和其他有效的过渡属性。
¥Both pageTransition
and layoutTransition
keys accept TransitionProps
as JSON serializable values where you can pass the name
, mode
and other valid transition-props of the custom CSS transition.
export default defineNuxtConfig({
app: {
pageTransition: {
name: 'fade',
mode: 'out-in' // default
},
layoutTransition: {
name: 'slide',
mode: 'out-in' // default
}
}
})
name
属性,则还必须相应地重命名 CSS 类。¥If you change the name
property, you also have to rename the CSS classes accordingly.要覆盖全局 transition 属性,请使用 definePageMeta
为单个 Nuxt 页面定义页面或布局过渡,并覆盖在 nuxt.config
文件中全局定义的任何页面或布局过渡。
¥To override the global transition property, use the definePageMeta
to define page or layout transitions for a single Nuxt page and override any page or layout transitions that are defined globally in nuxt.config
file.
<script setup lang="ts">
definePageMeta({
pageTransition: {
name: 'bounce',
mode: 'out-in' // default
}
})
</script>
禁用过渡效果
¥Disable Transitions
可以为特定路由禁用 pageTransition
和 layoutTransition
:
¥pageTransition
and layoutTransition
can be disabled for a specific route:
<script setup lang="ts">
definePageMeta({
pageTransition: false,
layoutTransition: false
})
</script>
或者,在 nuxt.config
中全局设置:
¥Or globally in the nuxt.config
:
export default defineNuxtConfig({
app: {
pageTransition: false,
layoutTransition: false
}
})
JavaScript 钩子
¥JavaScript Hooks
对于高级用例,你可以使用 JavaScript 钩子为 Nuxt 页面创建高度动态和自定义的转换效果。
¥For advanced use-cases, you can use JavaScript hooks to create highly dynamic and custom transitions for your Nuxt pages.
这种方式为 JavaScript 动画库(例如 GSAP)提供了完美的用例。
¥This way presents perfect use-cases for JavaScript animation libraries such as 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>
Transition
组件中可用的其他 JavaScript hooks 的信息。动态过渡效果
¥Dynamic Transitions
要使用条件逻辑应用动态过渡,你可以利用内联 中间件 为 to.meta.pageTransition
分配不同的过渡名称。
¥To apply dynamic transitions using conditional logic, you can leverage inline middleware to assign a different transition name to to.meta.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>
<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
过渡:
¥The page now applies the slide-left
transition when going to the next id and slide-right
for the previous:
使用 NuxtPage 进行过渡
¥Transition with NuxtPage
当 <NuxtPage />
在 app.vue
中使用时,可以使用 transition
属性配置过渡效果,以全局激活过渡效果。
¥When <NuxtPage />
is used in app.vue
, transitions can be configured with the transition
prop to activate transitions globally.
<template>
<div>
<NuxtLayout>
<NuxtPage :transition="{
name: 'bounce',
mode: 'out-in'
}" />
</NuxtLayout>
</div>
</template>
definePageMeta
覆盖。视图转换 API(实验性)
¥View Transitions API (experimental)
Nuxt 附带了 视图转换 API 的实验性实现(参见 MDN)。这是一种令人兴奋的新方法,可以实现原生浏览器过渡效果,它(除其他功能外)能够在不同页面上的不相关元素之间过渡。
¥Nuxt ships with an experimental implementation of the View Transitions API (see MDN). This is an exciting new way to implement native browser transitions which (among other things) have the ability to transition between unrelated elements on different pages.
你可以查看 https://nuxt-view-transitions.surge.sh 和 StackBlitz 上的源代码 的演示。
¥You can check a demo on https://nuxt-view-transitions.surge.sh and the source on StackBlitz.
Nuxt 集成正在积极开发中,但可以通过配置文件中的 experimental.viewTransition
选项启用:
¥The Nuxt integration is under active development, but can be enabled with the experimental.viewTransition
option in your configuration file:
export default defineNuxtConfig({
experimental: {
viewTransition: true
}
})
可能的值包括:false
、true
或 'always'
。
¥The possible values are: false
, true
, or 'always'
.
如果设置为 true,如果用户浏览器符合 prefers-reduced-motion: reduce
(推荐),Nuxt 将不会应用过渡效果。如果设置为 always
,Nuxt 将始终应用过渡效果,你可以自行决定是否尊重用户的偏好。
¥If set to true, Nuxt will not apply transitions if the user's browser matches prefers-reduced-motion: reduce
(recommended). If set to always
, Nuxt will always apply the transition and it is up to you to respect the user's preference.
默认情况下,所有 pages 都启用视图转换,但你可以设置其他全局默认值。
¥By default, view transitions are enabled for all pages, but you can set a different global default.
export default defineNuxtConfig({
app: {
// Disable view transitions globally, and opt-in on a per page basis
viewTransition: false
},
})
可以通过在页面的 definePageMeta
中设置 viewTransition
键来覆盖页面的默认 viewTransition
值:
¥It is possible to override the default viewTransition
value for a page by setting the viewTransition
key in definePageMeta
of the page:
<script setup lang="ts">
definePageMeta({
viewTransition: false
})
</script>
experimental.viewTransition
选项,逐页覆盖视图转换才会生效。¥Overriding view transitions on a per-page basis will only have an effect if you have enabled the experimental.viewTransition
option.如果你还使用 Vue 过渡(例如 pageTransition
和 layoutTransition
,参见上文)来实现与新的 View Transitions API 相同的效果,那么如果用户的浏览器支持较新的原生 Web API,你可能希望禁用 Vue 过渡。你可以通过创建包含以下内容的 ~/middleware/disable-vue-transitions.global.ts
来实现:
¥If you are also using Vue transitions like pageTransition
and layoutTransition
(see above) to achieve the same result as the new View Transitions API, then you may wish to disable Vue transitions if the user's browser supports the newer, native web API. You can do this by creating ~/middleware/disable-vue-transitions.global.ts
with the following contents:
export default defineNuxtRouteMiddleware(to => {
if (import.meta.server || !document.startViewTransition) { return }
// Disable built-in Vue transitions
to.meta.pageTransition = false
to.meta.layoutTransition = false
})
已知问题
¥Known Issues
- 如果你在页面设置函数中执行数据提取,则可能需要暂时重新考虑使用此功能。(根据设计,视图转换会在 DOM 更新过程中完全冻结它们。)我们正在考虑将视图转换限制在
<Suspense>
解析之前的最后时刻,但在此期间,如果你有此需求,你可能需要仔细考虑是否采用此功能。