カテゴリーに関連付くブログ記事一覧を表示しよう【Nuxt.js×Contentful】
  • 2022.02.02に公開
  • ブログ構築TS
  • 7. コンテンツページ構築
  • No.3 / 8

今回達成すること

カテゴリーコンテンツページに、カテゴリーに関連付く記事一覧を表示します。

2022-02-02 22-52-15

関連付くブログ記事を取得する方法

カテゴリーに関連記事を取得するには、2パターン存在します。

  1. Vuexのpostsにフィルターをかけ、現在のカテゴリーIDと一致する記事一覧を取得する
  2. Vuexに、カテゴリーIDごとに振り分けたcategoryPostsオブジェクトを用意する
「2」のcategoryPostsのイメージ
categoryPosts: {
  'categoryID 1': [<categoryID 1に紐づいたposts配列>],
  'categoryID 2': [<categoryID 2に紐づいたposts配列>],
}

どちらでも動きますが、今回は2の「categoryPostsオブジェクトを用意する」を採用します。

予め整理したオブジェクトに格納した方が、色々な場所で使い回せる。というのが最大の理由です。

VuexにcategoryPostsを用意する

store/index.tsに、カテゴリーID毎に振り分けられたcategoryPostsを作成します。

categoryPostsの型を用意する

categoryPostsは、Vuexのstateで用意するので、store/types/index.tsに型を宣言します。

export interface BlogPost {}下に追加してください。

store/types/index.ts
// 追加
// カテゴリー関連posts
export type CategoryPosts = { 
  [key: string]: BlogPost[] 
}

stateを用意する

store/index.tscategoryPostsオブジェクトを用意します。

store/index.ts
// CategoryPosts 追加
import { BlogCategory, BlogPost, BlogTag, CategoryPosts } from './types'

export const state = () => ({
  ...
  // 追加
  categoryPosts: {} as CategoryPosts
})

actionメソッドを用意する

categoriresをループして、CategoryID毎にpostsのフィルターを行うgetCategoryPosts()メソッドを追加します。

store/index.ts
export const actions = actionTree({ state, getters, mutations }, {
  ...
  // 追加
  // categoryId別のBlogPost配列を作成する
  getCategoryPosts ({ state, commit }) {
    const categoryPosts: CategoryPosts = {}

    for (const category of state.categories) {
      const categoryId: string = category.sys.id

      categoryPosts[categoryId] =
        state.posts.filter(post =>
          post.fields.category.sys.id === categoryId
        )
    }
    commit('setCategoryPosts', categoryPosts)
  }
})
  • categoryPosts ... オブジェクトの中身は、{ 'categoryId': BlogPost[] } となる。

mutationを用意する

commit先のミューテーションを用意します。

store/index.ts
export const mutations = mutationTree(state, {
  ...
  // 追加
  setCategoryPosts (state: RootState, payload: CategoryPosts) {
    state.categoryPosts = payload
  }
})

nuxtServerInitからアクションを呼び出す

作成したアクションメソッドは、nuxtServerInit()内で呼び出しサーバーサイドで処理を行います。

今回のアプリでは、

  • サーバー側で必要なデータを全て用意した後に
  • クライアントに処理を移行する

設計としています。

store/index.ts
export const actions = actionTree({ state, getters, mutations }, {
  async nuxtServerInit ({ dispatch }, _nuxtContext: Context) {
    await dispatch('getContentfulApi')
    // 追加
    dispatch('getCategoryPosts')
  },
})

これでCategoryID毎に振り分けられたブログ記事一覧のオブジェクトが作成できました。

カテゴリー関連記事を表示しよう

categories/_slug.vueに現在のカテゴリーに関連づく記事一覧を表示してみましょう。

pages/categories/_slug.vue
// categoryPosts 追加
type AsyncData = void | {
  category: BlogCategory
  categoryPosts: BlogPost[]
}

@Component
export default class CategoriesSlugPage extends Vue {
  validate ({ params }: Context): boolean {
    return !!params.slug
  }

  asyncData ({ app: { $accessor }, params, error }: Context): AsyncData {
    const category: BlogCategory | undefined =
      $accessor.categories.find((category: BlogCategory) =>
        category.fields.slug === params.slug
      )

    if (!category) {
      return error({
        statusCode: 404,
        message: 'This page could not be found'
      })
    }

    // 追加
    const categoryPosts: BlogPost[] = $accessor.categoryPosts[category.sys.id]

    return {
      category,
      // 追加
      categoryPosts
    }
  }

  • categoryPosts[category.sys.id] ... 整理したデータを用意することで、CategoryIDを指定するだけで関連記事を取得できるようになる。

<template>内には、categoryPostsv-forでループします。

pages/categories/_slug.vue
<template>
  <v-container>
    <nuxt-link
      to="/"
    >
      Home
    </nuxt-link>

    <h2>
      カテゴリー
    </h2>

    <div>
      Category slug: {{ category.fields.slug }}
    </div>

    <div>
      Category title: {{ category.fields.title }}
    </div>

    <h2>
      カテゴリー関連記事
    </h2>

    <ul>
      <li
        v-for="(post, i) in categoryPosts"
        :key="`post-${i}`"
      >
        [{{ post.fields.category.fields.title }}]
        {{ post.fields.title }}
      </li>
    </ul>
  </v-container>
</template>

カテゴリーコンテンツページを確認してみましょう。

同じカテゴリーのブログ記事一覧が表示されました。

2022-02-02 22-52-15

今回の作業は以上です。

% git commit -am "Add categoryPosts for categories/_slug.vue"

まとめと次回

今回はVuexにCategoryID毎に整理した記事一覧のオブジェクトを用意し、コンテンツページに関連記事を表示しました。

次回は、NuxtのInject機能を使って共有メソッドを置くクラスを作成します。

そしてasyncData()内のエラーの処理を、共通メソッドとして呼び出します。

下記をInjectを使って共通メソッドとする
return error({
  statusCode: 404,
  message: 'This page could not be found'
})
あなたの力になれること
私自身が独学でプログラミングを勉強してきたので、一人で学び続ける苦しみは痛いほど分かります。そこで、当時の私がこんなのあったら良いのにな、と思っていたサービスを立ち上げました。周りに質問できる人がいない、答えの調べ方が分からない、ここを聞きたいだけなのにスクールは高額すぎる。そんな方に向けた単発・短期間メンターサービスを行っています。
独学プログラマのサービス
ブログ構築TSの投稿
1
  • Nuxt.js×TypeScript開発環境構築
  • /
  • #01
Nuxt.jsをローカルPCに立ち上げよう
2
  • Nuxt.js×TypeScript開発環境構築
  • /
  • #02
Nuxt.jsプロジェクトをGitHubにPushしよう
3
  • Nuxt.js×TypeScript開発環境構築
  • /
  • #03
nuxt-property-decoratorのインストールとTypeScriptのセットアップ
1
  • Vuetifyセットアップ
  • /
  • #01
TypeScript環境のNuxt.jsにVuetifyを導入しよう
2
  • Vuetifyセットアップ
  • /
  • #02
VuetifyにカスタムCSSを追加してSASS変数を理解しよう
3
  • Vuetifyセットアップ
  • /
  • #03
VuetifyにカスタムSVGアイコンを追加しよう
1
  • NetlifyCLIを使ったNuxtデプロイ
  • /
  • #01
Netlify CLIをインストールして本番環境のサイトを作成しよう
2
  • NetlifyCLIを使ったNuxtデプロイ
  • /
  • #02
netlify.tomlを使ってNuxt.jsをNetlifyに手動デプロイしよう
1
  • Contentfulモデル構築
  • /
  • #01
Contentfulの料金とCommunityプランの無料枠を理解する
2
  • Contentfulモデル構築
  • /
  • #02
Contentfulへ新規会員登録、ロケールの変更、API Keyの発行を行う
3
  • Contentfulモデル構築
  • /
  • #03
Contentful ブログカテゴリーモデルを作成しよう
4
  • Contentfulモデル構築
  • /
  • #04
Contentful カテゴリーモデルに1対1で関連づくblogPostモデルを作成しよう
5
  • Contentfulモデル構築
  • /
  • #05
Contentful ブログ記事に1対多で関連づくplogTagモデルを作成しよう
6
  • Contentfulモデル構築
  • /
  • #06
Contentful カテゴリー・ブログ記事・タグコンテンツを作成しよう
1
  • Nuxt.js×Contentfulセットアップ
  • /
  • #01
Nuxt.js×Contentfulセットアップ。モジュールのインストールからAPI Keyの登録まで
2
  • Nuxt.js×Contentfulセットアップ
  • /
  • #02
Contentful APIリクエストの実行 Nuxt.jsにブログコンテンツを表示しよう
3
  • Nuxt.js×Contentfulセットアップ
  • /
  • #03
ContentfulAPIをNetlifyにデプロイしよう【Nuxt FullStaticのasyncDataとfetch】
1
  • Vuex×TypeScriptセットアップ
  • /
  • #01
Vuexの型付け vuex-module-decoratorsとnuxt-typed-vuexどちらを使用するか
2
  • Vuex×TypeScriptセットアップ
  • /
  • #02
nuxt-typed-vuexのインストールとセットアップ。Vuexの型定義と呼び出し方
3
  • Vuex×TypeScriptセットアップ
  • /
  • #03
VuexにContentfulの型定義ファイルとnuxtServerInitを追加しよう
4
  • Vuex×TypeScriptセットアップ
  • /
  • #04
VuexにContentfulAPIレスポンスを保存してVueファイルに表示しよう
1
  • コンテンツページ構築
  • /
  • #01
ブログアプリのページ設計とNuxt.jsの動的ルーティングについて理解しよう
2
  • コンテンツページ構築
  • /
  • #02
カテゴリーのコンテンツページを作成しよう【Nuxt.js×Contentful】
3
  • コンテンツページ構築
  • /
  • #03
カテゴリーに関連付くブログ記事一覧を表示しよう【Nuxt.js×Contentful】
4
  • コンテンツページ構築
  • /
  • #04
injectを使用して共通エラー処理メソッドを作成しよう【Nuxt×TypeScript】
5
  • コンテンツページ構築
  • /
  • #05
NuxtChildを使用してブログ記事ページを作成しよう【Nuxt.js×TypeScript】
6
  • コンテンツページ構築
  • /
  • #06
タグ一覧ページとタグ関連づく記事一覧を表示しよう【Nuxt.js×TypeScript】
7
  • コンテンツページ構築
  • /
  • #07
プライバシーポリシーページを作成しよう【Nuxt.js×TypeScript】
8
  • コンテンツページ構築
  • /
  • #08
@nuxtjs/i18nのインストールとセットアップ。ページタイトルの翻訳化【TypeScript】
1
  • NetlifyFunctionsを使った検索機能
  • /
  • #01
Netlify Functionsを使ってクエリを返す関数を作成しよう【Nuxt.js×TypeScript】
2
  • NetlifyFunctionsを使った検索機能
  • /
  • #02
Netlify Functionsプロジェクトをデプロイしよう【Nuxt.js×TypeScript】
3
  • NetlifyFunctionsを使った検索機能
  • /
  • #03
Nuxt.js × axiosセットアップ Netlify Functionsにリクエストを行う準備をしよう
4
  • NetlifyFunctionsを使った検索機能
  • /
  • #04
オリジン•CORS•プリフライトリクエストを理解する【Nuxt.js×Netlify Functions】
5
  • NetlifyFunctionsを使った検索機能
  • /
  • #05
Netlify Functionsを使ってフォームバリデーション機能を構築しよう【Nuxt.js】
6
  • NetlifyFunctionsを使った検索機能
  • /
  • #06
ツールバーに表示する検索フォームを作成しよう【Nuxt.js×TypeScript】
7
  • NetlifyFunctionsを使った検索機能
  • /
  • #07
検索ページを作成しよう【Vue propsとTypeScriptの書き方 解説】
8
  • NetlifyFunctionsを使った検索機能
  • /
  • #08
Netlify FunctionsからContentfulAPIリクエストを送ろう【Nuxt.js】
9
  • NetlifyFunctionsを使った検索機能
  • /
  • #09
検索ページに「もっと見る」ボタンを実装しよう【Nuxt.js×TypeScript】
1
  • ブログMarkdown対応
  • /
  • #01
@nuxtjs/markdownitのインストールとセットアップ【Nuxt.js×TypeScript】
2
  • ブログMarkdown対応
  • /
  • #02
Nuxt.js×markdown-it 外部リンクを別タブで開くプラグインを追加しよう
3
  • ブログMarkdown対応
  • /
  • #03
Nuxt.js×markdown-it 内部リンクをVueRouterで高速にページ遷移しよう
4
  • ブログMarkdown対応
  • /
  • #04
Nuxt.js×markdown-it アンカーリンクとブログ目次を自動生成しよう
独学プログラマ
独学でも、ここまでできるってよ。
CONTACT
Nuxt.js制作のご依頼は下記メールアドレスまでお送りください。