このブログはmicroCMS + Nuxt3で構築しています。
記事に複数のタグを参照するようにしているのですが、タグ一覧に紐づいている記事の数を表示させるようにしてみました。
こういう感じです。
Algorithm
のタグを参照している記事は7件、Next.js
は7件、AWS
は1件ということになります。
ちなみに被参照コンテンツの数はCMS上からは確認できます。
しかしながら、APIを叩いた際には、被参照コンテンツの数は現状返ってこないようです。
なので、紐づく記事の数を表示させるにはちょっと工夫をする必要があります。
今回は簡単ですが、タグに紐づく記事の数を表示させる方法についてまとめました。
ざっと思いつくところでは以下の方法があると思いました。
私は後者の方法を採用しました。
1.の方法は計算量は少なそうですが、取得APIをタグの数だけ飛ばさなくてはならないのがネックだと考えました。
2.の方法は一見して無駄な計算が多そうです。
しかし、私のブログは記事数は現在100程度で、タグは多くて一つの記事に2つか3つです。
なので、高々300回程度の計算で数え上げることができます。これは十分高速に行えると判断しました。
記事やタグの数が増えても投げるAPIの数は変わらない、というメリットもあります。
まずは記事一覧コンテンツを受け取り、idごとに数えあげる関数を作成します。
import { PostList } from '../types/blog'
type Data = {
[key: string]: number
}
// タグを参照している記事の数を返す
export const getTagReferencedCount = (postList: PostList) => {
const ret: Data = {}
for (const post of postList.contents) {
for (const tag of post.tag) {
if (ret[tag.id]) {
ret[tag.id]++
} else {
ret[tag.id] = 1
}
}
}
return ret
}
まずは{id:個数}という形で記録するオブジェクトを初期化しています。
その後は地道に記事データを繰り返して、その中のタグを繰り返して…という二重ループで、個数をカウントアップして返します。
次にタグ一覧でコンポーネントで呼び出せばいいです。
// タグ一覧
const { data: tags } = await useFetch<TagList>('/api/tagList')
const queries: MicroCMSQueries = {
limit: 1000,
fields: 'tag'
}
// 全件の記事
const { data: posts } = await useFetch('/api/postList', { params: queries })
// つくった関数を呼び出す
const countData = getTagReferencedCount(posts.value)
limit=1000としているのは、とりあえず超えそうにない、という値を適当に入れています。
もう少し確実にやるなら、一度APIを飛ばしてtotalCountを取得したのちに、再度limitを設定して投げればいいでしょう。
最後にテンプレート部分ではv-for
でタグのIDを出力している最中にcountData
から個数を取得してタグラベルコンポーネントに渡します。
<template>
<div class="inline">
<span v-for="tag in tagList" :key="tag.id">
<TagLabel :tag="tag" :isInline="true" :colorClass="getClass(tag.id)" :count="countData[tag.id]" />
</span>
</div>
</template>
後は受け取った個数を表示させればいいでしょう。
具体的な実装についてはこのブログのgithubリポジトリを参照していただければと思います。
関連するコードは下記の部分です。
タグ一覧部分のコンポーネント
https://github.com/qlitre/qlitre-weblog-nuxt3/blob/master/src/components/TagInline.vue
参照されているタグを数える関数
https://github.com/qlitre/qlitre-weblog-nuxt3/blob/master/src/libs/referenced-count.ts
タグ単体のコンポーネント
https://github.com/qlitre/qlitre-weblog-nuxt3/blob/master/src/components/TagLabel.vue