程式化導航 (Programmatic Navigation)
<router-link> 很好用,但有時候我們需要在程式碼中決定何時跳轉(例如:登入成功後跳回首頁、表單送出後跳到列表頁)。
這時我們就需要用到 Router 實體提供的方法。
一、 獲取 Router 實體
在 Vue 3 Composition API 中:
javascript
import { useRouter } from "vue-router";
const router = useRouter();NOTE
useRouter 必須在 setup() 或 <script setup> 的頂層呼叫。如果你在一般的函數中呼叫它,會拿到 undefined。
二、 核心方法
Vue Router 提供了三個主要方法,它們模仿了原生 window.history API 的行為。
1. router.push(location)
這對應到 history.pushState。它會向 history stack 添加一個新記錄,所以使用者按「上一頁」會回到原本的頁面。
常見用法:
javascript
// 字串路徑
router.push("/home");
// 物件路徑 (更推薦)
router.push({ path: "/home" });
// 帶查詢參數 (Query) -> /register?plan=private
router.push({ path: "/register", query: { plan: "private" } });
// 帶 Hash -> /about#team
router.push({ path: "/about", hash: "#team" });WARNING
Params 陷阱:如果你使用 path,params 會被忽略!
javascript
// 錯誤!params 不生效
router.push({ path: "/user", params: { userId: "123" } });
// 正確:配合 name 使用
router.push({ name: "user", params: { userId: "123" } });
// 或者直接組字串
router.push(`/user/${userId}`);2. router.replace(location)
這對應到 history.replaceState。它會 替換 當前的 history 記錄。 使用者按「上一頁」不會 回到原本的頁面。
適用場景:
- 登入後的重導向(不希望使用者按上一頁回到登入頁)。
- 表單提交後的狀態變更。
javascript
router.replace({ path: "/home" });3. router.go(n)
這對應到 history.go(n)。在 history stack 中前進或後退 n 步。
javascript
router.go(1); // 下一頁
router.go(-1); // 上一頁 (等同於 window.history.back())三、 等待導航完成
router.push 和 router.replace 其實會回傳一個 Promise。
這在某些情境下非常有用,例如你需要確保頁面已經切換完畢才執行某些動畫或數據加載。
javascript
await router.push("/about");
console.log("導航完成!現在在 About 頁面");四、 導航故障 (Navigation Failures)
有時候導航會失敗,例如:
- 使用者已經在
/home,你又push('/home')。 - 導航被
beforeEach守衛攔截 (return false)。
Vue Router 4 不會像 v3 那樣在這些情況下拋出 Error (讓你的 Console 變紅)。它會回傳一個 NavigationFailure 物件。
如果你需要偵測這類情況:
javascript
import { NavigationFailureType, isNavigationFailure } from "vue-router";
const failure = await router.push("/dashboard");
if (failure) {
if (isNavigationFailure(failure, NavigationFailureType.aborted)) {
console.log("導航被守衛攔截");
} else if (isNavigationFailure(failure, NavigationFailureType.duplicated)) {
console.log("導航重複 (已在該頁面)");
}
}總結
- 使用
useRouter()獲取實體。 push會留歷史記錄,replace不會。- 注意:
path不能與params混用,請改用name搭配params。
下一章,我們將介紹如何讓路由配置更乾淨解耦:命名視圖 (Named Views)。