Vue.jsとNuxt.jsのrouterの違い
Vue.jsでは、ルーティングを設定する際にrouter/index.jsなどで自分で自由に設定することができます。
カスタマイズなど自由自在で、pages配下のファイルの置き場所に関係なく、pathやcomponentやname、それにmetaなどを設定することができました。
このあたりを参照。
ti-tomo-knowledge.hatenablog.com
metaは本当に便利ですよね。
Nuxt.jsでのルーティングは便利だけどデメリットも
Vue.jsでは自由にカスタマイズがしやすかったrouterも、Nuxt.jsになってからは仕組みが変わります。
Nuxt.jsでは、pages配下のファイル(ディレクトリ)構成によって、勝手にルーティングが変わってしまうのです。
例えば以下のファイル(ディレクトリ)構成の場合、
pages test_dir1 page1.vue page2.vue test_dir2 page3.vue page4.vue
page1.vueにアクセスしたい場合
→test_dir1/pages1にアクセス
page2.vueにアクセスしたい場合
→test_dir1/pages2
page3.vueにアクセスしたい場合
→test_dir2/pages3
page4.vueにアクセスしたい場合
→test_dir2/pages4
のように自動で(言い方帰れば勝手に)ルーティングされます。
ルーティングの結果はビルド後に.nuxt/router.jsに作成されます。
単純なルーティングしかないプロジェクトであれば問題ありません。
ただ、例えばpage1.vueのテンプレートを他のURLでも表示させたい場合はどうしたら良いのでしょう。
また、meta要素はどうやって設定するのでしょう。
どうやってNuxtでルーティングをカスタマイズする?
例えばpage1.vueのテンプレートを他のURLでも表示させたい場合の方法についてです。
方法は簡単で、nuxt.config.jsでextendRoutesを使用します。
ja.nuxtjs.org
参照。
例えば以下のようにすれば、「/page5」にアクセスすることでtest_dir1配下にあるpage1.vueのページを開くことができます。
export default { router: { extendRoutes (routes, resolve) { routes.push({ name: 'page5', path: 'page5', component: resolve(__dirname, 'pages/test_dir1/page1.vue') }) } } }
ちなみにextendRoutesでは以下のようにmetaを設定することも可能です。
export default { router: { extendRoutes (routes, resolve) { routes.push({ name: 'page5', path: 'page5', component: resolve(__dirname, 'pages/test_dir1/page1.vue'), meta: {meta1: 'meta1です', meta2: 'meta2です'} }) } } }
ルーティングを設定した後は、sortRoutesを使用して最後にソートをかけた方が.nuxt/router.jsで後から確認がしやすいです。
import { sortRoutes } from '@nuxt/utils' export default { router: { extendRoutes (routes, resolve) { routes.push({ name: 'page5', path: 'page5', component: resolve(__dirname, 'pages/test_dir1/page1.vue'), meta: {meta1: 'meta1です', meta2: 'meta2です'} }) sortRoutes(routes) } } }
metaの設定は?
metaに関しては、新しくルーティングを追加する場合は上記のようにextendRoutesのroutes.pushで設定可能です。
では、ディレクトリ構成から自動で生成されたルーティングに対してmetaタグを設定する場合はどうしたらよいでしょう?
ちょっと無理矢理な方法になりますが、ここでもextendRoutesを使用します。
.nuxt/router.jsを確認いただければわかるのですが、自動で作成されたルーティングに対してはディレクトリ構成によりnameが付与されています。
test_dir1/pages1であれば「test_dir1-page1」、test_dir1/pages2であれば「test_dir1-page2」のように。
なので、そのnameを持つルーティングに対してmetaの設定を追加すれば良いのです。
export default { router: { extendRoutes (routes, resolve) { routes.forEach(route => { if (route.name === 'test_dir1-page1') { route.meta = {meta1: 'meta1です', meta2: 'meta2です'} } if (route.name === 'test_dir1-page2') { route.meta = {meta1: 'meta1です', meta2: 'meta2です'} } }) } } }
ちょっと応用になりますが、以下のように「test_dir1.vue」や「test_dir2.vue」を設定してその中で「
pages test_dir1 page1.vue page2.vue test_dir2 page3.vue page4.vue test_dir1.vue test_dir2.vue
そのような場合はforEachの中にforEachを設定すれば同じようにmetaの設定が可能になります。
export default { router: { extendRoutes (routes, resolve) { routes.forEach(route => { route.children.forEach(childRoute => { if (childRoute.name === 'test_dir1-page1') { childRoute.meta = {meta1: 'meta1です', meta2: 'meta2です'} } if (childRoute.name === 'test_dir1-page2') { childRoute.meta = {meta1: 'meta1です', meta2: 'meta2です'} } }) }) } } }