Aug 14, 2020

「Nuxtでプログを構築しよう!!」の7回目。今回は記事の内容を表示してみよう。

「Nuxt でプログを構築しよう!!」の 7 回目です。今回は Mardown で作成した記事を前回作成した記事一覧から該当する記事の内容を表示するようにしたいと思います。

記事を検索する Article コンポーネントの作成

記事を検索するコンポーネントを作成します。構造は記事一覧のコンボーネントと似ていますので、特に説明はいらないと思います。記事を検索したら Card コンポーネントに検索した article オブジェクトを渡しています。引数の digest は、記事の概要を表示するか記事の内容を表示するか判断するフラグです。

<template>
  <div class="posts">
    <div class="cards">
      <Card :digest="false" :article="article" />
    </div>
  </div>
</template>
<script lang="ts">
import { defineComponent, reactive, computed, useContext } from 'nuxt-composition-api';
type Props = {
  target: string;
};
export default defineComponent({
  props: {
    target: String,
  },
  setup(props: Props) {
    const state = reactive<{
      article: object;
    }>({
      article: object,
    });
    const target = props.target;
    // dummy stub
    const lang = 'ja';
    const article = computed(() => state.article);
    // @ts-ignore
    const { $content, params } = useContext();
    const slug = params.value.slug;
    getArticle(target, lang, slug);
    async function getArticle(target: string, lang: string, slug: string) {
      state.article = await $content(target, lang, slug).fetch();
    }
    return {
      article,
    };
  },
});
</script>

記事を表示する Card コンポーネントの作成

記事のオブジェクトを受け取ったら、タイトルや日付、記事の内容を表示します。また記事一覧用のダイジェスト版も作成できるようにします。ダイジェスト版は、記事の内容そのものは表示しないで、タイトル、概要、日付と記事のイメージ画像のみを表示します。

カードイメージにしたいので、コンポーネント名は、Card としました。Props として digest と article オブジェクトを受け取ります。digest が true の場合は、記事概要を表示して、section タグのクラス名を crad-digest にします。digest が false の場合は、記事内容を表示し、section タグのクラス名は、card としています。

このクラスをダイナミックに変えることで、表示画面のスタイルを変えています。また、Markdwon の記事内容は nuxt-content コンポーネントに article オブジェクトを渡すだけで html に変換され表示されます。

<template>
  <section :class="[digest === true ? 'card-digest' : 'card']">
    <img class="card-img" :src="article.img" />
    <div class="card-content">
      <p class="card-title">{{ article.title }}</p>
      <div>
        <nuxt-content :document="article" />
      </div>
      <p class="card-footer">
        {{ formatDate(article.createdAt) }}
      </p>
    </div>
  </section>
</template>
<script lang="ts">
import { defineComponent } from 'nuxt-composition-api';
type Props = {
  type: string;
  article: object;
};
export default defineComponent({
  props: {
    digest: {
      type: Boolean,
      required: true,
    },
    article: {
      type: Object,
      required: true,
    },
  },
  setup() {
    function formatDate(date: Date) {
      const options = { year: 'numeric', month: 'long', day: 'numeric' };
      let result = '';
      if (typeof date !== 'undefined') {
        result = new Date(date).toLocaleDateString('en', options);
      }
      return result;
    }
    return { formatDate };
  },
});
</script>

スクリプトには、記事の日付をローカル日付に変換する関数をいれてあります。

検証

index!

早速、VSCode から実行して初期画面の記事一覧をクリックして記事が表示されるか試してみます。直接、http://localhost:3000/blog/article05 としても該当の記事を表示することが確認できたと思います。

次回は少し休憩して、スタイルシートをいじって クール?な画面に変身したいと思います。