Appearance
【Router】路由过渡特效 👌
要点速览
- 使用
Transition包裹router-view的渲染组件以实现页面切换动画 - 通过
name指定 CSS 过渡前缀,mode控制进出时序(out-in/in-out) - 利用
v-slot="{ Component, route }"读取当前路由与元信息,动态应用过渡 - 设置
:key强制重新渲染以触发过渡,建议使用route.fullPath - 可在全局后置守卫中为不同页面写入
to.meta.transition实现差异化过渡 - CSS 建议采用
opacity/transform结合硬件加速,避免布局抖动 style scoped场景需用:deep(.class)作用到子组件根元素
概念与本质
路由过渡是通过 Transition 组件在页面切换时为即将进入与离开的组件添加一组钩子类名,从而让 CSS 动画在正确的时机生效。核心是用插槽拿到当前要渲染的组件并包裹它:
vue
<template>
<router-view v-slot="{ Component }">
<Transition name="fade" mode="out-in">
<component :is="Component" />
</Transition>
</router-view>
</template>动态过渡(基于路由)
通过 route.meta.transition 统一管理不同页面的过渡名:
vue
<template>
<router-view v-slot="{ Component, route }">
<Transition :name="route.meta.transition || 'fade'" mode="out-in">
<component :is="Component" />
</Transition>
</router-view>
</template>在全局后置守卫中按路径写入:
js
router.afterEach((to) => {
switch (to.path) {
case "/panel-left":
to.meta.transition = "slide-left";
break;
case "/panel-right":
to.meta.transition = "slide-right";
break;
default:
to.meta.transition = "fade";
}
});对应样式:
css
.slide-left-enter-active,
.slide-left-leave-active {
transition: transform 0.25s ease;
}
.slide-left-enter-from,
.slide-left-leave-to {
transform: translateX(16px);
}
.slide-left-enter-to,
.slide-left-leave-from {
transform: translateX(0);
}
.slide-right-enter-active,
.slide-right-leave-active {
transition: transform 0.25s ease;
}
.slide-right-enter-from,
.slide-right-leave-to {
transform: translateX(-16px);
}
.slide-right-enter-to,
.slide-right-leave-from {
transform: translateX(0);
}强制过渡(Key)
当路由组件被“复用”时可能不会触发预期过渡,需添加 key 强制重新渲染。为了包含 query/hash 的变化,推荐:
vue
<template>
<router-view v-slot="{ Component, route }">
<Transition name="fade" mode="out-in">
<component :is="Component" :key="route.fullPath" />
</Transition>
</router-view>
</template>实际开发注意事项
- 动画属性选择:优先
transform/opacity,避免触发布局/重绘;设置will-change: transform, opacity - 时序控制:页面栈切换常用
out-in,避免新旧页面叠加导致闪烁 - Scoped 样式:父组件定义的过渡类需用
:deep(.fade-enter-active)作用到子组件根元素 - 可访问性:在
@media (prefers-reduced-motion: reduce)下降低或禁用动画 - 初次渲染:需要首屏过渡时使用
appear属性
示例(Scoped 与首屏过渡):
vue
<template>
<router-view v-slot="{ Component, route }">
<Transition name="fade" mode="out-in" appear>
<component :is="Component" :key="route.fullPath" />
</Transition>
</router-view>
</template>css
:deep(.fade-enter-active),
:deep(.fade-leave-active) {
transition: opacity 0.2s ease;
}
:deep(.fade-enter-from),
:deep(.fade-leave-to) {
opacity: 0;
}
@media (prefers-reduced-motion: reduce) {
:deep(.fade-enter-active),
:deep(.fade-leave-active) {
transition: none;
}
}