深入 RouterView 與頁面轉場 (Transitions)
在 Vue 2 的時代,我們可以簡單地把 <router-view> 包在 <transition> 裡面。但在 Vue 3,這一切變了。
為什麼?因為 router-view 不再是一個單純的組件,它變成了一個「插槽容器 (Slot Container)」。
這一章,我們將解開 v-slot 的奧秘,並實現各種炫砲的轉場效果。
一、 為什麼寫法變了?
在 Vue 2:
html
<!-- Vue 2 (已過時) -->
<transition>
<router-view></router-view>
</transition>在 Vue 3 (Vue Router 4),如果你這樣寫,console 會噴黃字警告,而且動畫不會生效。正確的寫法是:
html
<!-- Vue 3 標準寫法 -->
<router-view v-slot="{ Component }">
<transition name="fade" mode="out-in">
<component :is="Component" />
</transition>
</router-view>這裡發生了什麼事?
v-slot="{ Component }":RouterView會把它「當前匹配到的組件」透過 Slot Props 傳出來。<component :is="Component">: 我們拿到這個組件,手動把它渲染出來。<transition>: 因為我們現在手握組件實體,所以可以自由地包在transition(或keep-alive) 裡面。
這種設計雖然囉嗦,但給了我們極大的靈活性。以前我們很難對不同的路由做不同的處理,現在因為多了一層 Slot,我們可以拿到 route 對象做判斷。
二、 基礎轉場 (Fade Effect)
最常見的「淡入淡出」效果。
Template
html
<router-view v-slot="{ Component }">
<transition name="fade" mode="out-in">
<component :is="Component" />
</transition>
</router-view>CSS
css
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.5s ease;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}mode="out-in": 這非常重要!它讓舊組件「先消失 (Out)」,新組件「再出現 (In)」。如果不加這個,你會看到兩個頁面同時存在一瞬間,版面會亂跳。
三、 動態轉場 (Dynamic Transitions)
如果我想讓「進入內頁」時向左滑,「回到上一頁」時向右滑,該怎麼做?
我們可以利用 Route Meta 來告訴 Router 該用哪個動畫。
1. 定義 Meta
在 router/index.js 中:
javascript
const routes = [
{
path: "/",
component: Home,
meta: { transition: "slide-left" }, // 自定義欄位
},
{
path: "/about",
component: About,
meta: { transition: "slide-right" },
},
];2. 在 RouterView 中使用
html
<router-view v-slot="{ Component, route }">
<!-- 使用 route.meta.transition 作為 name -->
<transition :name="route.meta.transition || 'fade'" mode="out-in">
<component :is="Component" />
</transition>
</router-view>四、 進階:基於路由深度的轉場
上面的方法還是得手動寫死。更聰明的做法是:比較 to 與 from 的層級深度。
javascript
// router.afterEach 用來動態計算動畫
router.afterEach((to, from) => {
const toDepth = to.path.split("/").length;
const fromDepth = from.path.split("/").length;
if (toDepth < fromDepth) {
to.meta.transition = "slide-right"; // 回上一層 -> 向右滑
} else if (toDepth > fromDepth) {
to.meta.transition = "slide-left"; // 進下一層 -> 向左滑
} else {
to.meta.transition = "fade"; // 同層級 -> 淡入淡出
}
});總結
Vue Router 4 的 <router-view> 改用 Slot API 是一個巨大的進步,它解鎖了無限的可能性。
- 必須使用 v-slot:
<router-view v-slot="{ Component }">。 - 動態組件渲染:
<component :is="Component">。 - 模式選擇: 大多數情況下請加上
mode="out-in"。
理解了這個結構,下一章我們要挑戰最艱難的任務:把 <keep-alive> 也加進去。