Nuxt 系列 - #3 搞懂路由怎麼搞
關於路由
Nuxt.js 會依據在 pages 目錄內的 vue 檔案自動生成路由配置。目前有提供4種路由,分別為基礎路由、動態路由、嵌套路由與動態嵌套路由,接下來會分別說明4種路由的配置方式與規則。還有關於自訂換頁的特效與 middleware 的用途說明。
另外在頁面之間要切換路由時,建議使用 <nuxt-link>。目前 <nuxt-link> 與 <router-link> 用法一致,可至 Vue Router documentation 查閱所有資訊。
<template>
<nuxt-link to="/">Home page</nuxt-link>
</template>
基礎路由
以下檔案結構
pages/
∟ user/
∟ index.vue
∟ one.vue
∟ index.vue
會自動產生以下路由設定
.vue 檔案的數量會與路由產生的數量相同
router: {
routes: [
{
name: 'index',
path: '/',
component: 'pages/index.vue'
},
{
name: 'user',
path: '/user',
component: 'pages/user/index.vue'
},
{
name: 'user-one',
path: '/user/one',
component: 'pages/user/one.vue'
}
]
}
這邊要特別說明的是 name 為 user-one 這個路由,可以發現這個 name 使用 - 符號來做分隔 user 與 one,這個是 nuxt 預設的設定。如果想要調整這個部份可至 nuxt.config.js 檔案中設定 router.routeNameSplitter。
動態路由
使用"下底線"定義 .vue 檔案名稱或資料夾名稱,就會被視為使用參數的動態路由。
以下檔案結構
pages/
∟ _slug/
∟ comments.vue
∟ index.vue
∟ users/
∟ _id.vue
∟ index.vue
會自動產生以下路由設定
router: {
routes: [
{
name: 'index',
path: '/',
component: 'pages/index.vue'
},
{
name: 'users-id',
path: '/users/:id?',
component: 'pages/users/_id.vue'
},
{
name: 'slug',
path: '/:slug',
component: 'pages/_slug/index.vue'
},
{
name: 'slug-comments',
path: '/:slug/comments',
component: 'pages/_slug/comments.vue'
}
]
}
請注意 name 為 users-id 的路由 path 帶有 :id? 參數,代表 id 這個參數為非必要的,所以當你的 path 為 /users 時,也會符合 users-id 這個路由設定,此時 id 的值將會是 undefined。
如果想讓 id 參數為必要的,可於 pages/users/_id.vue 增加 validate 方法來檢核參數值。當方法 return 不為 true、Promise 中 resolve 不為 true 或發生錯誤,都會自動顯示 404 或 500 錯誤頁面。
export default {
validate ({ params }) {
// Must be a number
return /^\d+$/.test(params.id)
}
}
更多關於路由參數檢核的資訊,請參考 API Pages validate
嵌套路由
建立嵌套路由需要建立一個 .vue 檔案,同時建立一個與 .vue 檔案名稱相同的目錄,裡面存放被嵌套的子組件。並且在一開始建立的 .vue 檔案中增加 <nuxt-child/> 來顯示子組件的內容。
以下檔案結構
pages/
∟ users/
∟ _id.vue
∟ index.vue
∟ users.vue
會自動產生以下路由設定
router: {
routes: [
{
path: '/users',
component: 'pages/users.vue',
children: [
{
path: '',
component: 'pages/users/index.vue',
name: 'users'
},
{
path: ':id',
component: 'pages/users/_id.vue',
name: 'users-id'
}
]
}
]
}
於 pages/users.vue 中增加 <nuxt-child/>
<template>
<div class="container">
<h1>pages/users.vue file</h1>
<nuxt-child/>
</div>
</template>
動態嵌套路由
比較少見的應用場景,設定上相對複雜,但規則基本上就是依照前面所說的動態路由搭配嵌套路由去設定。以下為官方範例,供大家參考。
以下檔案結構
pages/
∟ _category/
∟ _subCategory/
∟ _id.vue
∟ index.vue
∟ _subCategory.vue
∟ index.vue
∟ _category.vue
∟ index.vue
會自動產生以下路由設定
router: {
routes: [
{
path: '/',
component: 'pages/index.vue',
name: 'index'
},
{
path: '/:category',
component: 'pages/_category.vue',
children: [
{
path: '',
component: 'pages/_category/index.vue',
name: 'category'
},
{
path: ':subCategory',
component: 'pages/_category/_subCategory.vue',
children: [
{
path: '',
component: 'pages/_category/_subCategory/index.vue',
name: 'category-subCategory'
},
{
path: ':id',
component: 'pages/_category/_subCategory/_id.vue',
name: 'category-subCategory-id'
}
]
}
]
}
]
}
轉場特效
使用 Vue.js 的 <transition> 組件實現路由切換時的轉場特效。
Nuxt.js 預設的 transition 名稱為 page
所以要讓每次切換路由時都有特定的轉場特效,就要在全域的樣式檔案中增加下列樣式,這邊使用淡入、淡出效果為範例。
.page-enter-active, .page-leave-active {
transition: opacity .5s;
}
.page-enter, .page-leave-active {
opacity: 0;
}
如果想要指定特定頁面的轉場效果的話,就在頁面組件中設定 transition 屬性值為 page 以外的名稱,並在全域樣式檔案中加上對應的樣式即可。
頁面組件設定
export default {
transition: 'special'
}
增加全域樣式設定
.special-enter-active, .special-leave-active {
transition: opacity .3s;
}
.special-enter, .special-leave-active {
opacity: 0.3;
}
Middleware
在一個頁面或是一組頁面渲染之前執行一個自訂的函式(function),Nuxt.js規定此類的程式應放置於 middleware/ 的目錄內。
Middleware 函式傳入 the context 為參數,並且可以是非同步的方法。
建立 middleware/stats.js
import axios from 'axios'
export default function ({ route }) {
return axios.post('http://my-stats-api.com', {
url: route.fullPath
})
}
可將 middleware 設定於 nuxt.config.js,使用 router.middleware
export default {
router: {
middleware: ['stats']
// or
middleware: 'stats'
}
}
或者設定於 page/index.vue 與 layouts/default.vue
export default {
middleware: ['stats']
// or
middleware: 'state'
}