Nuxt.js でコンポーネント作成。 ブログのモジュールを作成する
Nuxt.js でコンポーントの作成方法について記載します。
ブログなどで、人気ランキングモジュールや、関連記事モジュールなど、複数のページで共通の情報を表示する場合があります。
そういった場合にコンポーネントとして切り出しておくことで、共通化することができます。
目次
作りたいもの
ブログのモジュールとして、同一カテゴリの記事を表示するコンポーネントを作成します。
実際のブログで運用しているイメージとしては下記の様なものになります。(このブログ自体のもの)
今回は、少し簡略化してコンポーネントに切り分けて、コンポーネントを表示するだけのアプリケーションを作ってみます。
環境・利用技術
今回は下記のVue, Nuxt関連の技術を扱って作っていきます。
- Vue.js
- Nuxt.js
- Vuetify
- Vuex
データソース
今回はデータソースは json に書き込んだブログ記事の情報を読み込むことにします。
{
"contentsMap": {
"id1": {
"title": "テスト記事1",
"description": "テスト記事1",
"category": "category1",
"body": "テスト記事1"
},
"id2": {
"title": "テスト記事2",
"description": "テスト記事2",
"category": "category1",
"body": "テスト記事2"
},
"id3": {
"title": "テスト記事3",
"description": "テスト記事3",
"category": "category2",
"body": "テスト記事3"
},
"id4": {
"title": "テスト記事4",
"description": "テスト記事4",
"category": "category2",
"body": "テスト記事4"
},
"id5": {
"title": "テスト記事5",
"description": "テスト記事5",
"category": "category2",
"body": "テスト記事5"
},
"id6": {
"title": "テスト記事6",
"description": "テスト記事6",
"category": "category1",
"body": "テスト記事6"
}
}
}
上記jsonの内容を contents/contentsMap.json
という名前で保存しておきます。
contents/
└── contentsMap.json
この情報を今回はVuexで管理します。
実際にはAPI等で引いて利用する場合もあると思いますが、その場合もVuexで管理すれば同じように扱えるかと思います。
Vuex
vuex自体に関しては、以前にこちらの記事を書いています。
Nuxt.js で Vuex を使う | mintsu's blog
Vuexを利用するため、 store
ディレクトリ以下に記事を管理するvuexファイルとしてarticle.js
を作成します。
store/
└── article.js
vuexのファイルの内容は下記になります。
import { contentsMap } from '~/contents/contentsMap.json'
export const state = () => ({
articleList: contentsMap
})
export const getters = {
findArticlesByCategory: state => (category) => {
return Object.values(state.articleList).filter(a => a.category === category)
}
}
contentsMap.jsonを読み込んで、 state に設定します。
今回は参照しかないため、gettersのみ定義します。
gettersの内容は findArticlesByCategory
というメソッドを定義し、カテゴリ名を指定してcontentsMap.から指定したカテゴリの記事情報のみを返却します。
ここまでで、データソース取得の準備は整いました。
コンポーネントを作成する
ここではコンポーネントはcomponents
ディレクトリ以下に置くことにします。
components/
└── CategoryArticleList.vue
コンポーネントの内容は下記のようになります。
<template>
<v-layout row wrap>
<v-flex x12 sm12 md12>
<h3 class="headline">{{ category }} カテゴリの記事</h3>
</v-flex>
<v-flex v-for="(article, idx) in articleList" :key="idx" xs12 sm12 md12>
<v-card style="width: 100%">
<v-card-text>
<p>{{ article.title }}</p>
</v-card-text>
</v-card>
</v-flex>
</v-layout>
</template>
<script>
export default {
props: { // propsを使うと引数を受け取れるようになる
category: {
type: String,
required: true
}
},
computed: {
articleList() {
return this.$store.getters[
'article/findArticlesByCategory'
](this.category)
}
}
}
</script>
ポイントとしてはカテゴリ名をpropsで受け取れるようにしているところです。
propsで受け取ったカテゴリを、 computed でvuexから取得するときに利用します。
computed
のarticleList
メソッド内でVuexのgetterを呼び出します。
下記が該当の部分です。
this.$store.getters['article/findArticlesByCategory'](this.category)
Vuexのモジュールモードで引数ありの場合はこのような指定になります。
引数にpropsで受け取ったカテゴリを指定することで、特定のカテゴリの記事リストを取得しています。
コンポーネントの表示
作成したコンポーネントを表示してみます。
下記はpages側のvueファイルです。
pages/
└── componentSample.vue
componentSample.vue
<template>
<v-layout column justify-center align-center>
<v-flex xs12 sm8 md6>
<CategoryArticleList category="category1" /> // コンポーネントの利用箇所
</v-flex>
</v-layout>
</template>
<script>
import CategoryArticleList from '~/components/CategoryArticleList.vue' // コンポーネント読み込み
export default {
components: {
CategoryArticleList // コンポーネントの登録
}
}
</script>
コンポーネントを利用するためには、<script>
内でコンポーネントの登録をする必要があります。 インポートして、componentsでインポートしたコンポーネントを登録します。
import CategoryArticleList from '~/components/CategoryArticleList.vue' // コンポーネント読み込み
export default {
components: {
CategoryArticleList // コンポーネントの登録
}
}
</script>
コンポーネントを登録すると、カスタム要素としてテンプレート側で利用できるようになります。
上の例ではテンプレート側でCategoryArticleList
というタグとして利用できるようになっています。
属性のcategory
はコンポーネント作成時に使ったpropsと対応します。
<CategoryArticleList category="category1" />
実際に表示してみた結果がこちらになります。
他のページでも、同じようにコンポーネントの登録さえすれば、CategoryArticleList
というタグを呼び出だすだけでカテゴリ記事リストのモジュールが表示できるので、再利用もでき、簡潔に書けるため便利ですね。
実際に作った今回のサイト
component-sample
最後に
今回のポイント
- コンポーネントを使うことで、共通のUIなどを定義できる
- データの受け渡しはpropsを使う
- コンポーネントの利用側は、使うコンポーネントを登録することで、カスタム要素として利用できる