2018.10.31現在。nuxt-2.2.0
で確認。
問題:ドキュメント通りでは必須パラメータにならない場合がある
https://nuxtjs.org/guide/routing/#dynamic-routes
Dynamic Routingについてのドキュメントを見ると、パラメータを必須にしたい場合は、pages/_id.vue
ではなく、pages/_id/index.vue
にファイルを配置しろと記述されている。
これはpages
直下のルーティングには適用されるが、ディレクトリ掘ると対応されず常に任意になる。
例えばpages/post/_id/index.vue
は生成された.nuxt/router.js
を見るとパラメータがid?
で任意になっている。(追記参照、post.vue
が存在しない場合)
再現手順
$ yarn create nuxt-app testhoge
$ mkdir -p testhoge/pages/post1 && touch testhoge/pages/post1/_id.vue
$ mkdir -p testhoge/pages/post2/_id && touch testhoge/pages/post2/_id/index.vue
<template>
<div>post1: ... {{ $route.params.id }}</div>
</template>
<template>
<div>post2: ... {{ $route.params.id }}</div>
</template>
$ yarn dev
解決策:対象のコンポーネントで、validate
を実装してパラメータを制限する
<template>
<div>required params.id: ... {{ $route.params.id }}</div>
</template>
<script>
export default {
validate({ params }) {
// params.idの存在チェックをしとかないと、正規表現マッチ時にstring変換されてtestを通ってしまう場合がある
return params.id && /^\w+$/.test(params.id)
}
}
</script>
validate対応で、pages/post/_id.vue
とpages/post/_id/index.vue
は結局どちらでも同じに動作する。
...
どちらのファイル配置を使うかは、ルーティングをネストするかどうかで変わってくるけど、迷うなら_id/index.vue
を使うほうが良さそう。
親コンポーネントを作りたい場合や、親コンポーネントなしで兄弟コンポーネントがある場合にも対応しやすい。
■_id配下に子ページコンポーネントがそもそも無いならどっちでもおk
post/
└ _id.vue
post/
└ _id/
└ index.vue
■_id.vueを親コンポーネントにする場合
post/
├ _id.vue (<nuxt-child/>を含む)
└ _id/
├ index.vue
└ comment.vue
■親コンポーネントは使わないない
post/
└ _id/
├ index.vue
└ comment.vue
追記
nuxtのルーティング生成のコードを読んだ限り、そもそも、親コンポーネントの無いディレクトリ区切りは想定されていないっぽい。
https://github.com/nuxt/nuxt.js/blob/39b558f59c0ecb5aa40bf709ca5dff83a151b20b/packages/common/src/utils.js#L213
つまりコンポーネントを入れ子にする場合は
post/
└ _id/
├ index.vue
└ comment.vue
ではなく
post.vue (<nuxt-child/>を含む)
post/
└ _id/
├ index.vue
└ comment.vue
と、ディレクトリと同名の親コンポーネントを定義する必要があるようだ。
そうすると、nuxtビルドでパラメータ必須でRouter設定が生成される。
まあ、これで設定可能なのは必須/任意だけで、その他validationは本文中の通りComponent.validate
を使わないといけない。
ファイル配置での自動ルーティングはあまり気にせずvalidate
でのパラメータチェックを重視するのが良さそう。