ファイルシステムルーティング
Nuxt は pages ディレクトリにある Vue ファイルの木構造に基づいて、vue-router の設定を自動的に生成します。pages ディレクトリに .vue ファイルを作成すると、特別な設定をせずとも基本的なルーティングが動作するようになります。
動的なルーティングやネストされたルートを生成したり、ルーターのプロパティをより細かく設定したりする必要がある場合があるでしょう。この章では、ルーターを最大限に活用するために知るべきことすべてを説明します。
<template>
<NuxtLink to="/">Home page</NuxtLink>
</template>
ルーティングの基礎
下記のような木構造のとき:
pages/
--| user/
-----| index.vue
-----| one.vue
--| index.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'
}
]
}
動的なルーティング
ユーザーやブログ記事の一覧を API から取得する場合など、ルートの名前を決定することができない場合があります。私たちはこれを動的なルーティングと呼びます。動的なルーティングを生成するには、.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'
}
]
}
users-id
と名付けられたルートに :id?
というパスがありますが、これはこの :id
が必須ではないことを表します。もし必須にしたい場合は、代わりに users/_id
ディレクトリ内に index.vue
ファイルを作成してください。ルートパラメーターへのローカルアクセス
ローカルページやコンポーネント内の現在のルートパラメータは、this.$route.params.{parameterName}
を参照することでアクセスすることができます。例えば、動的な ユーザーページ(users/_id.vue
)があり、ユーザーまたはプロセス情報を読み込むために id
パラメーターにアクセスしたい場合、次のような変数にアクセスできます: this.$route.params.id
ネストされたルート
Nuxt は vue-router の子ルートを使ってルートをネストさせることができます。ネストされたルートの親コンポーネントを定義するには、子ビューを含むディレクトリと同じ名前の Vue ファイルを作成する必要があります。
.vue
ファイル)内に NuxtChild コンポーネント を含めることを忘れないでください。下記のような木構造のとき:
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'
}
]
}
]
}
動的でネストされたルート
あまり頻繁に使う場面はありませんが、Nuxt は動的な親ルーティングの中に動的な子ルーティングを持つことが可能です。
下記のような木構造のとき:
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'
}
]
}
]
}
]
}
未知の動的でネストされたルート
もし URL 構造の深さが不明な場合は、ネストされたパスに動的にマッチさせる _.vue
ファイルを使うことができます。これはより詳細なルートにマッチしなかったリクエストをハンドリングします。
下記のような木構造のとき:
pages/
--| people/
-----| _id.vue
-----| index.vue
--| _.vue
--| index.vue
次のようにリクエストをハンドリングします:
/ -> index.vue
/people -> people/index.vue
/people/123 -> people/_id.vue
/about -> _.vue
/about/careers -> _.vue
/about/careers/chicago -> _.vue
_.vue
ページのロジックに依存します。ルーターの拡張
Nuxt のルーティングを拡張する方法はいくつかあります:
- router-extras-module を使ってページのルートパラメータをカスタマイズする
-
@nuxtjs/router コンポーネントを使い、独自の
router.js
で Nuxt router を上書きする -
nuxt.config.js
内で router.extendRoutes プロパティを使う
router プロパティ
router プロパティを使って Nuxt のルーター (vue-router) をカスタマイズできます。
export default {
router: {
// Nuxt router をカスタマイズする
}
}
Base:
アプリケーションのベース URL です。例えばシングルページアプリケーション全体を /app/
配下で配信したい場合、base に /app/
を設定します。
extendRoutes
Nuxt によって生成されるルーティングを拡張したい場合があるでしょう。それは extendRoutes
オプションで実現できます。
独自のルートを追加する例:
export default {
router: {
extendRoutes(routes, resolve) {
routes.push({
name: 'custom',
path: '*',
component: resolve(__dirname, 'pages/404.vue')
})
}
}
}
ルートをソートしたい場合、@nuxt/utils
の sortRoutes(routes)
関数を使うことができます:
import { sortRoutes } from '@nuxt/utils'
export default {
router: {
extendRoutes(routes, resolve) {
// ここにルートを追加します ...
// それらをソートします
sortRoutes(routes)
}
}
}
export default {
router: {
extendRoutes(routes, resolve) {
routes.push({
path: '/users/:id',
components: {
default: resolve(__dirname, 'pages/users'), // または routes[index].component
modal: resolve(__dirname, 'components/modal.vue')
},
chunkNames: {
modal: 'components/modal'
}
})
}
}
}
fallback
history.pushState をサポートしていないブラウザにおいて、モードが history に設定されている場合に、ルーターを hash モードにフォールバックするかどうかを制御します。
mode
ルーティングのモードを設定します。サーバーサイドレンダリングのため、この設定を変更することは非推奨です。
parseQuery / stringifyQuery
カスタムクエリ構文解析関数 / 文字列化関数を提供します。
routeNameSplitter
Nuxt が使うルート名の区切り文字を変更したい場合があるでしょう。それは設定ファイル内の routeNameSplitter
オプションを使用して実現できます。pages/posts/_id.vue
というページファイルがあるとします。Nuxt はプログラムに従ってルート名を生成します。この場合は posts-id
です。routeNameSplitter
の設定を /
に変更することによって posts/id
へ変更されます。
export default {
router: {
routeNameSplitter: '/'
}
}
scrollBehavior
scrollBehavior
オプションを使って、ページ間遷移のスクロール位置について独自の振る舞いを定義することができます。このメソッドはページがレンダリングされるたびに毎回呼び出されます。
v2.9.0 以降で利用可能:
ファイルを利用してルーターの scrollBehavior を上書きすることができます。このファイルは app フォルダに配置する必要があります。
~/app/router.scrollBehavior.js
.
すべてのルートに置いて強制的にトップまでスクロールさせる例:
export default function (to, from, savedPosition) {
return { x: 0, y: 0 }
}
trailingSlash
v2.10 以降で利用可能:
このオプションを true に設定した場合、すべてのルートの末尾にスラッシュが追加されます。false に設定した場合、それらは取り除かれます。
export default {
router: {
trailingSlash: true
}
}
router.trailingSlash
に undefined
(デフォルトの値)以外の値を設定した場合、どちらかのルートは機能しなくなります。したがって、301 リダイレクトは適切に行われ、内部リンクは正しく適応される必要があります。trailingSlash
を true
に設定する場合、example.com/abc/
のみが機能し、example.com/abc
は機能しません。false に設定する場合はその逆になります。











































