# 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>
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>
2
3
4
5
6
7
8
9
10
11
12
13
# replace 屬性
若我們不希望在瀏覽器留下 URL 的歷史紀錄,可以在 <router-link> 加上 replace 屬性:
<router-link to="/abc" replace></router-link>
這樣在背後執行時會呼叫 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>
2
3
4
5
6
7
類似這樣的做法來處理網頁連結是否要加上 active 的 CSS。
但是當我們使用 Vue Router 的 <router-link> 之後,就可以利用 router-link-active 與 router-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>
2
3
4
5
6
7
完全不用對任何東西加工即可使用。
而 router-link-active 與 router-link-exact-active 的差別在於 router-link-active 是模糊比對,router-link-exact-active 是準確比對。
當我們今天 URL 在根目錄 「/」 的時候:
<router-link to="/">Home</router-link>
實際在網頁上的內容會渲染成:
<a href="/" class="router-link-active router-link-exact-active">Home</a>
另外,若我們目前的位置在 /list/123:
<router-link to="/list">List</router-link>
實際在網頁上的內容會渲染成:
<a href="/list" class="router-link-active">List</a>
因為我們目前的 URL 在 /list 下層的 /list/123,所以對應的 List 連結只會有 router-link-active 這個 Class,而不會出現 router-link-exact-active。
# <router-link> 與 v-slot
<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>
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>
2
3
渲染的結果就會是:
<button role="link">About Us</button>
這裡有幾個地方需要注意的是,若不希望外層被 <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' })
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)
2
3
4
5