Nuxtコンテンツでブログを作成する
以下のtutorialを参考にNuxtのcontentモジュールの学習を進めてみたのでやったこと学んだことをアウトプットしてみる。
ローカルでnodejs環境を作るのが久しぶりでnodebrewのセットアップ時にハマった。
Nuxtプロジェクト作成
npx create-nuxt-app nuxt-project-sample
上記の記事に合わせるために以下の問いにはヘッドレスCMSを選択する
? Project name: nuxt-project-sample
? Programming language: JavaScript
? Package manager: Npm
? UI framework: None
? Nuxt.js modules: Content - Git-based headless CMS
? Linting tools: (Press <space> to select, <a> to toggle all, <i> to invert selection)
? Testing framework: None
? Rendering mode: Universal (SSR / SSG)
? Deployment target: Server (Node.js hosting)
? Development tools: (Press <space> to select, <a> to toggle all, <i> to invert selection)
? What is your GitHub username? kensukeueno
? Version control system: Git
コンテンツモジュールはcontent/
ディレクトリ内のファイルを読み取る。
markdown、csv、yaml、json、json5、またはxmlを解析できるらしい。
フロントマター内の画像は静的フォルダーにないといけない。
記事のYAMLに含まれる画像をレンダリングするには、画像を静的フォルダーに配置するか、構文を使用する必要があります。@ nuxt / contentは独立し
:src="require(
~/assets/images/${article.img})"
ているため、記事のコンテンツに含まれる画像は常に静的フォルダーに配置する必要があります。 Webpack。静的フォルダーはwebpackを通過しませんが、assetsフォルダーは通過します。
NuxtLinkタグとは?
Vuejsのrouter-link
を拡張しているもの。
<a>
は外部ページ、<NuxtLink>
は内部ページという使い分け方をする。
また<NuxtLink>
はパフォーマンスを高めるのに有効らしい。
h2,h3タグのリンク等はtoc変数で取得できる
これをループさせるだけでリンクが作成できる。(ここではarticleページ内のtocを取得している)
/* toc変数にはh2,h3のみが格納される */
/* articleはページ情報 */
<li v-for="link of article.toc" :key="link.id">
<NuxtLink :to="`#${link.id}`">{{ link.text }}</NuxtLink>
</li>
Componentを使用する
nuxt.config.jsに以下の設定することでcomponentがグローバルに使えるようになる。
export default {
components: true
}
呼び出したComponentはtemplateタグで上書きできる
component以下
templateタグを設置せずにComponentを呼び出した場合はComponent内のtemplateがデフォルトで呼び出される。
InfoBox.vue (component)
<template>
<div class="p-4 mb-4 text-white bg-blue-500">
<p><slot name="info-box">default</slot></p>
</div>
</template>
markdown(呼び出し先)
<info-box>
<template #info-box>
<!-- template内を上書きできる。templateがなければデフォルトのComponentの値が表示される -->
This is a vue component inside markdown using slots
</template>
</info-box>
mdやxmlファイル等にコードブロックを埋め込む
Content モジュールでは、Prism の自動インクルージョンによりCodeブロックをカンマ3つが囲えば自動で作成してくれるようになっている。以下のようにすればいい。
(```)
<p>code styling is easy</p>
(```)
NuxtLinkで動的にlink先を指定する。(to
→ :to
にする)
リンク先を変数名にしたいだとかってときは以下のように:to
を使ってあげればいい
<NuxtLink
v-if="prev"
:to="{ name: 'blog-slug', params: { slug: prev.slug } }"
>
asyncDataとは?
asyncDataの引数はContextオブジェクトの分割代入
contentオブジェクトやurlを受け取れたりする。ほかにもいろいろ受け取れるので気になったら調べる感じでいい。
const contextObject = { $content: ~, params: ~ }
async asyncData({ $content, params }) {
const article = await $content('articles', params.slug).fetch()
return { article, prev, next }
}
記事に対してAPI経由で情報を取得する
content/以下のxml等のファイルの場所を、以下のようにcontentにアンダーバー(_)をつけて取得できる。(以下ローカルでのAPI取得用URL)
http://localhost:3000/_content/~
記事を取得するAPIをwhereクエリで絞り込む
以下のようなURLのパラメータを使って記事の著者名と一致した人のみ取得できるようにする。
http:// localhost:3000 / _content / articles?author.name = Maria
まずは、next.config.jsに以下のような記述が必要
export default {
content: {
nestedProperties: ['author.name']
}
}
そして以下のようにauthor.name
をwhereで指定すればいい。
async asyncData({ $content, params }) {
const articles = await $content('articles', params.slug)
.where({
'author.name': {
$regex: [params.author, 'i']
}
})
.fetch()
return {
articles
}
}
onlyメソッドとwithoutメソッド
上記で使ってきた$contentはグローバルなインスタンスであり様々なメソッドを持つ。
例えばonly()やwithoutもそのひとつである。
$content.onlyメソッドは引数の記事情報のみを抽出する。抽出したい情報が少ない場合に使うといい。
$content.withoutメソッドは引数の記事情報を除外する。抽出したい情報が多いときに使うといい。
watchメソッドで検索できるようにする
watchメソッドは基本的に[ プロパティ:データ ] のように定義するが、関数を指定することもできる。以下のようにすることでsearchQuery
に変更があったかどうかとwatchで監視できる。
また、searchQueryプロパティを検索フォームと双方向バインディングさせることでsearchQuery
に経由で処理を走らせる事ができる。
data() {
return {
searchQuery: ''
}
},
watch: {
async searchQuery(searchQuery) {
if (!searchQuery) {
this.articles = []
return
}
this.articles = await this.$content('articles')
.limit(6)
.search(searchQuery)
.fetch()
}