こんにちはこんにちは、Vue.js 初心者です。
さて、Vue.jsは強力なコンテンツ処理を秘めたフレームワークだと勝手に思ってるんですが、ページ作るたびにvue-routerに定義書いて、ページ分のコンポーネントファイルを作って、ひいひいコーディングするのは非常にナンセンスというかWordPressでええやん感が出ますね。
で、そんなはずは無えだろボケと思いまして、vue-routerを使ったページ量産構造が作れたのでメモしておく。
import Vue from 'vue';
import Router from 'vue-router';
// 普通のページ
import Top from '@/layouts/Top';
// 量産型ページ
import SinglePage from '@/layouts/SinglePage';
import SectionOne from '@/components/SectionOne';
import SectionTwo from '@/components/SectionTwo';
import PageNotFound from '@/components/PageNotFound';
Vue.use(Router);
export default new Router({
mode: 'history',
routes: [
{
path: '/',
name: 'Top',
component: Top,
},
{
path: '*',
component: SinglePage,
children: [
{
path: '/sec1',
component: SectionOne,
meta: {
title: 'うんこパラダイス',
breadcrumbs: [
{
path: '/sec1',
name: 'うんこパラダイス',
},
],
},
},
{
path: '/sec2',
component: SectionTwo,
meta: {
title: 'ちんちんぶらぶら',
breadcrumbs: [
{
path: '/hoge',
name: 'ほげ',
},
{
path: '/sec2',
name: 'ちんちんぶらぶら',
},
],
},
},
{
// ちなみにこれステータスが200になるから注意な
path: '*', // 見つかりません的な
component: PageNotFound,
},
],
},
],
});
見ての通り、path
を入れ子にしている。@/layouts/SinglePage.vue
ファイルを親として、パスをワイルドカードで指定、そのchildren
たちとしてpath
に合致する状態を作り出す。合致したら、そこで定義しているcomponent
(単数形なことに注意)が参照されて、<router-view>
を通して内容が置き換わる。
重要なのはmeta
フィールドで、ここの定義でもってページタイトルと、パンくずリストを構成させる。meta.breadcrumbs
で定義した配列とオブジェクトの数でもってパンくずリストを生成させたいのだ。
さて、量産型ページを司る親コンポーネントファイル(ここでは、レイアウトと称する)の設定をする。
<template lang="pug">
.page
Header
Breadcrumb(v-bind:breadcrumbs="breadcrumbs")
article
.title
h1
| {{ title }}
router-view
Footer
</template>
<script>
import Header from '@/components/Header';
import Breadcrumb from '@/components/Breadcrumb';
import Footer from '@/components/Footer';
export default {
name: 'SinglePage',
components: {
Header,
Breadcrumb,
Footer,
},
computed: {
title() {
// タイトルがvue-routerのmetaフィールドで指定されているか調べる
if( this.$route.matched.some( obj => obj.meta.title ) ){
// 存在するなら使う
return this.$route.meta.title
}
// ない場合
return '表題無設定'
},
breadcrumbs() {
// パンくずの定義がvue-routerのmetaフィールドでされているか調べる
if( this.$route.matched.some( obj => obj.meta.breadcrumbs ) ){
// 存在するなら使う
return this.$route.meta.breadcrumbs
}
// ない場合は、HOMEとだけ表示させる
return
}
},
};
</script>
こいつは、ページのDOMレイアウトを司ってるだけに徹してもらう。あと、vue-routerに定義されたmeta
フィールドがちゃんとあるかどうか、存在を確認させて、存在すればページタイトルとかにも使う。(title
要素もここで考慮したほうがいいかも)パンクズも、そのまま存在すれば引き継ぐ。
なお、さっきも書いた通り、ここでの<router-view>
が、router/index.js
で定義したchildren
配下のパスに合致したcomponent
に対応して置き換わる。難しいこと言ってるがパズルみたいなもんだ、実行すればわかるだろ。
あとは必要なページの中身を用意してみる。
<template lang="pug">
section
h2 うんこはえいえんのともだち
p ...
</template>
<script>
export default {
name: 'SectionOne',
};
</script>
<template lang="pug">
section
h2 ひろでんでんしゃでちんちんぶらぶら
p ...
</template>
<script>
export default {
name: 'SectionTwo',
};
</script>
<template lang="pug">
section
h2 名称未設定
p ...
</template>
<script>
export default {
name: 'PageNotFound',
};
</script>
いいですね。本質的な部分のみコンポーネント化されていて、とてもシンプルだと勝手に思い込む。
あとはパンくずだが、まあオブジェクトをもらってv-for
させるだけである。
<template lang="pug">
nav
ul
li
router-link(to="/")
| HOME
li(v-for="list in breadcrumbs")
router-link(v-bind:to="list.path")
| {{ list.name }}
</template>
<script>
export default {
name: 'Breadcrumb',
props: [
'breadcrumbs'
]
};
</script>
ここまでコンポーネント化されているので、必要があれば別にvue-router側でパンくずの定義をせず、APIとかあるならコンポーネント側でcomputed
して投げる形も良いと思う。
とにかくこうすると、量産ページ増えても、section
要素の中身をコンポーネントとして増やしていくだけでページ作れるので、よかったんじゃないかなーと思いました。まる。