MonkeyBinBin

被程式設計的猴子

Nuxt.js

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'
}

參考資料

Nuxt.js - Routing
Vue Router documentation