# 4-3 <router-link> 建立路由連結

前面我們曾經短暫介紹過 <router-link> 可以用來建立路由連結, 但它所提供的功能可不只是產生超連結而已,否則我們直接寫 <a> 標籤就好了。 這個小節就為讀者們介紹 <router-link> 的各種常見用法。

先從最基本的用法快速講起:

<router-link to="/">Go to Home</router-link>
<router-link to="/about">Go to About</router-link>

<!-- 實際的渲染結果 -->
<a href="/">Go to Home</a>
<a href="/about">Go to About</a>
1
2
3
4
5
6

像這樣 <router-link> 加上 to 屬性,可以快速建立一個超連結, 並與我們前一個小節介紹過的路由高度整合,達到無需重整即可讀取對應的 Vue.js 元件,並同時更新 URL 網址的效果。

# to 屬性

這個 to 屬性,除了可以直接給一段純文字的路徑外,也可以是這樣的形式:

<!-- 與 v-bind 綁定,省略 path -->
<router-link :to="'/home'">Home</router-link>

<!-- 指定 path,作用與前面一樣 -->
<router-link :to="{ path: '/home' }">Home</router-link>

<!-- 搭配具名路由 -->
<router-link :to="{ name: 'user', params: { userId: '123' }}">User</router-link>

<!-- 搭配 query 參數, 編譯後的結果會出現在 queryString: `/register?plan=private` -->
<router-link :to="{ path: '/register', query: { plan: 'private' }}">
  Register
</router-link>
1
2
3
4
5
6
7
8
9
10
11
12
13

# replace 屬性

若我們不希望在瀏覽器留下 URL 的歷史紀錄,可以在 <router-link> 加上 replace 屬性:

<router-link to="/abc" replace></router-link>
1

這樣在背後執行時會呼叫 Vue Router 的 router.replace() (預設為 router.push()) 來替換網址,實際效果類似 JavaScript 的 location.replace() 那樣,更新頁面之後不會在瀏覽器留下 URL 紀錄,所以我們也無法透過「上一頁」或「下一頁」的按鈕來切換狀態。

# active-class 與目前路由配對的樣式

當目前的 URL 與頁面上的連結相符的時候,過去我們可能會需要自行判斷 active 的 CSS Class,

<template>
  <ul>
    <li><a :class="{ 'active': location.pathname === '/' }" href="/">Home</a></li>
    <li><a :class="{ 'active': location.pathname === '/list' }" href="/list">List</a></li>
    <li><a :class="{ 'active': location.pathname === '/about' }" href="/about">About</a></li>
  </ul>
</template>
1
2
3
4
5
6
7

類似這樣的做法來處理網頁連結是否要加上 active 的 CSS。

但是當我們使用 Vue Router 的 <router-link> 之後,就可以利用 router-link-activerouter-link-exact-active 這兩組 Class 名稱來處理:

<template>
  <ul>
    <li><router-link to="/">Home</router-link></li>
    <li><router-link to="/list">List</router-link></li>
    <li><router-link to="/about">About</router-link></li>
  </ul>
</template>
1
2
3
4
5
6
7

完全不用對任何東西加工即可使用。

router-link-activerouter-link-exact-active 的差別在於 router-link-active 是模糊比對,router-link-exact-active 是準確比對。

當我們今天 URL 在根目錄 「/」 的時候:

<router-link to="/">Home</router-link>
1

實際在網頁上的內容會渲染成:

<a href="/" class="router-link-active router-link-exact-active">Home</a>
1

另外,若我們目前的位置在 /list/123

<router-link to="/list">List</router-link>
1

實際在網頁上的內容會渲染成:

<a href="/list" class="router-link-active">List</a>
1

因為我們目前的 URL 在 /list 下層的 /list/123,所以對應的 List 連結只會有 router-link-active 這個 Class,而不會出現 router-link-exact-active

<router-link> 元件也可以與我們在第二章所介紹過的插槽 - Scoped Slots 搭配使用。

<router-link
  to="/about"
  custom
  v-slot="{ href, route, navigate, isActive, isExactActive }">
  <NavLink :active="isActive" :href="href" @click="navigate">
    {{ route.fullPath }}
  </NavLink>
</router-link>
1
2
3
4
5
6
7
8

<router-link> 所提供的 v-slot 可以有這些屬性:

  • href: 解析後的網址,提供給 <a>href 目標字串。
  • route: 回傳完整的 Route 物件。
  • navigate: 觸發路由的事件函式,必要時會阻止此事件執行。
  • isActive: 若回傳值為 true,則表示目前路由的 URL 與目標相同,可用來取代預設的 router-link-active
  • isExactActive: 若回傳值為 true,則表示目前路由的 URL 與目標「完全」相同,可用來取代預設的 router-link-exact-active

舉例來說,若我們希望將原本的 <router-link> 所渲染出來的 <a> 改為 <button>,那麼可以這樣做:

<router-link to="/about" custom v-slot="{ navigate }">
  <button @click="navigate" role="link">About Us</button>
</router-link>
1
2
3

渲染的結果就會是:

<button role="link">About Us</button>
1

這裡有幾個地方需要注意的是,若不希望外層被 <a> 標籤包覆, <router-link> 需要加上 custom 屬性。

另外,若未加上 @click="navigate" 處理對應的點擊事件,這個 <button> 在點擊時就不會有 URL 轉頁的效果。

小提醒

若你的 <a> 標籤有使用 target="_blank",則 navigate 會被忽略。

# 透過 router.push() / router.replace() 操作路由

在前面的範例裡,我們都透過 <router-link :to="..."> 來渲染出連結操作網站的路由, 如果我們希望透過程式來做到網站的導頁,就需要透過 Vue Router 所提供的 router.push()router.replace() 方法了。

router.push() 使用的方式與我們操作網址的概念大同小異,

// 透過字串指定 URL
router.push('/users/eduardo')

// 透過物件與 path 指定
router.push({ path: '/users/eduardo' })

// 與具名路由、params 搭配
router.push({ name: 'user', params: { username: 'eduardo' } })

// 以 query 指定目標的 query string
router.push({ path: '/register', query: { plan: 'private' } })

// 搭配 hash, 執行後的結果為 /about#team
router.push({ path: '/about', hash: '#team' })
1
2
3
4
5
6
7
8
9
10
11
12
13
14

router.replace() 方法使用的方式與 router.push() 完全一樣,唯一的差別是 router.replace() 不會在瀏覽器裡留下紀錄。

小提醒

說到瀏覽器紀錄,Vue Router 也提供 router.go() 方法來模擬 window.history.go(),例如:

// 到下一頁 (或下一個路由紀錄),等同 router.forward()
router.go(1)

// 到前一頁 (或前一個路由紀錄),等同 router.back()
router.go(-1)
1
2
3
4
5
Last Updated: 1/2/2021, 7:35:12 PM