Nuxt 3 內建基於檔案的路由可以快速實現頁面的路由配置,我們只需要在 pages
目錄下建立頁面,Nuxt 將會自動載入 Vue Router 來實現路由效果,目錄下的檔案通常是 Vue 的元件,也允許具有 .vue、.js、.jsx、.ts 或 .tsx 副檔名的檔案,本篇將分享一些建立路由的方式與需要自定義時該如何操作。
在 Nuxt 3 我們可以很快的建立出路由的頁面,例如新增 ./pages/about.vue 檔案,內容如下,我們就可以瀏覽 /about 來渲染出該頁面。
<template>
<div>
這裡是 /about
</div>
</template>
如果我們要使用路由連結,可以使用 <NuxtLink>
來建立路由連結來進行頁面的跳轉,下 ./pages/index.vue 程式碼,新增 /about 路由連結來進行頁面導航。
<template>
<div>
<h1>這裡是首頁</h1>
<NuxtLink to="/about">前往 About 頁面</NuxtLink>
</div>
</template>
如果你想要使用程式化的方式來控制路由,可以使用 router.push
,傳入 /about
來進行導航。
<script setup>
const router = useRouter()
router.push('/about')
</script>
這種使用 <NuxtLink>
元件或 router.push
函式來控制頁面導航至 /about 頁面,非常容易理解,但有些情況,你可能不是使用路由的路徑,而是以路由名稱甚至加上 params 來進行導航,那麼 <NuxtLink>
元件或 router.push
函式,所接收的 path 就需要自己來建構。
例如在元件傳入路由名稱跳轉到 about
<NuxtLink :to="{ name: 'about' }">前往 About 頁面</NuxtLink>
或者呼叫 router.push
函式傳入路由名稱跳轉到 about
router.push({
name: 'about',
})
在使用 Vue Router 時,你可以為路由建立路由名稱,這個具名的路由頁面,可以在導航時傳遞一個 path 物件並以 name 表示要前往的路由頁面名稱,例如上面的例子路由頁面名稱為 about
。
在 Nuxt 3 中,我們仍然可以傳遞 path 物件,但是你可能會不大清楚 name 要表示的路由名稱該從何得知呢?我們知道 Nuxt 3 採用基於檔案系統的路由,所以當路由初始化完成後,路由頁面的名稱也是根據這個檔案系統來命名。
以 ./pages/about.vue 為例,路由頁面名稱為 about
,使用的是檔案的名稱,挺直觀也容易理解。
而若是子目錄下的路由頁面呢?
以 ./pages/user/profile.vue 為例,路由頁面名稱以每一層目錄使用減號 -
來串接,最終路由名稱為 user-profile
。
而若是包含 params 參數的路由頁面呢?
以 ./pages/posts/[id].vue 為例,路由頁面名稱以中括號 []
內的文字作為下一個減號 -
後接續的名稱,最終路由名稱為 posts-id
。
整體上來說還算好理解推論,稍微整理一下成下列表格也能比較清楚得知自動產生的路由名稱。
頁面檔案 | 路由路徑 | 路由名稱 |
---|---|---|
pages/index.vue | / | index |
pages/about.vue | about | about |
pages/user/profile.vue | /user/profile | user-profile |
pages/posts/indev.vue | /posts | posts-index |
pages/posts/[id].vue | /posts/:id | posts-id |
自動產生的路由名稱,有部分情況可能會有衝突的可能,例如 ./pages/posts/[id].vue 與 ./pages/posts/id.vue,這兩個檔案產生的路由名稱皆為 posts-id
,這類情況可能導致無法產生預期的路由名稱或正確導航。
除了在開發時稍作留意,盡量避免衝突的可能性發生,倘若真的命名了可能發生衝突的頁面檔案,那就得倚靠自定義路由來分別定義這幾個頁面的路由名稱或路由規則。
你也可以在瀏覽頁面時,搭配開發工具 Nuxt DevTools、Vue DevTools 等工具來觀察路由及產生的路由名稱。如果你的專案導入並啟用 Nuxt DevTools,在 DevTools 的 Pages 分頁,就能快速的觀察檔案所對應的路由名稱與別名,方便你對路由頁面所產生的路由進行追蹤。
我們可以在專案目錄下建立一個 app
目錄,建立配置路由選項的檔案 ./app/router.options.js,檔案內容如下:
export default {
routes: (_routes) => [
{
name: 'home',
path: '/',
component: () => import('~/pages/home.vue').then(r => r.default || r),
},
],
}
這種建立與使用 router options 方式,會替換原本 Nuxt 3 基於檔案檔案系統的頁面路由,當這個路由函式若回傳 null
或 undefined
才會退回使用 Nuxt 3 的路由系統,也因此自定義路由後不能夠與基於檔案系統的路由同時使用。
pages:extend
hook 添加路由規則你可以使用 Nuxt 3 的 pages:extend
hook 來從掃描到的路由中添加、修改或刪除頁面路由,這種定義方式可以與基於檔案系統的路由同時使用,也就達到了可以擴展原本頁面路由的效果。
在 ./nuxt.config.ts 中 hooks 的 pages:extend
函式新增一個路由。
export default defineNuxtConfig({
hooks: {
'pages:extend' (pages) {
pages.push({
name: 'profile',
path: '/profile',
file: '~/pages/user/profile.vue',
})
},
},
})
修改頁面路由名稱 user-profile (頁面檔案:./pages/user/profile.vue) 的路由名稱為 profile
。
export default defineNuxtConfig({
hooks: {
'pages:extend' (pages) {
for (const page of pages) {
if (page.name === 'user-profile') {
page.name = 'profile'
}
}
},
},
})
刪除所有 /admin 路徑開頭的頁面。
export default defineNuxtConfig({
hooks: {
'pages:extend' (pages) {
const pagesToRemove = []
for (const page of pages) {
if (/^\/admin.*/.test(page.path)) {
pagesToRemove.push(page)
}
}
for (const page of pagesToRemove) {
pages.splice(pages.indexOf(page), 1)
}
},
},
})
如果自定義路由對你來說太過暴力,你只是想要讓頁面路徑具有別名,讓頁面可以有額外的路徑可以瀏覽,那麼你可以使用 definePageMeta
組合式函式來完成。
例如在 ./pages/user/profile.vue 定義路徑別名 /profile
,你就可以新增除了 /user/profile
外可以訪問的路徑:
<script setup>
definePageMeta({
alias: '/profile'
})
</script>
你也可以以陣列的方式來定義多個路徑別名。
<script setup>
definePageMeta({
alias: ['/profile', '/user-profile']
})
</script>
使用自定義頁面路由路徑的別名,要注意的是路徑雖然有額外得別名,但是路由的名稱仍會是原本頁面自動產生的路由名稱 user-profile
,所以在路由導航上也只能夠使用這個額外的別名路徑來跳轉頁面。
Nuxt 3 的路由規則的建制,歸功於基於檔案來產生路由的特性,你可以很方便的來建立頁面路由,而當需要額外擴展或添加別名等來控制路由的規則,那就需要使用一些額外的設定來操作,本篇整理了頁面檔案名稱所對應產生的路由路徑與常見的添加自定義路由的方式更多方法也可以參考官方文件。
感謝大家的閱讀,歡迎大家給予建議與討論,也請各位大大鞭小力一些:)
如果對這個 Nuxt 3 系列感興趣,可以訂閱
接收通知,也歡迎分享給喜歡或正在學習 Nuxt 3 的夥伴。
參考資料
很實用!當時專案想要自定義路由就有遇到類似的問題。
例如 /auth/sign-in 想要簡化為 /sign-in。
Nuxt 有很多很方便的內建功能,熟悉之後真的開發體驗很讚