Dec 20, 2020

Nuxt composition-apiで作成したVueファイルをtsファイルに機能分割してみた。

このホームページもそろそろリビルドしたいと思います。composition-api で作成した Vue ファイルから記事、コンテンツ読み込み処理を Vue ファイルから分離したいと思います。composition-api+typescript でいきます。

記事一覧 処理 を Articles Vue ファイルから分離

こちらが元々の Articles.vue ファイルになります。ここから記事一覧の読み込む処理を分離したいと思います。

/components/Articles.vue
  <tamlate>
    <div class="article-list">
      <div v-for="article of articles" :key="article.slug">
        <NuxtLink :to="{ name: 'blog-slug', params: { slug: article.slug } }">
          {{ article.title }}
        </NuxtLink>
      </div>
    </div>
  </template>
 
  <script lang="ts">
    import {defineComponent,reactive,computed,useContext} from 'nuxt-composition-l'
    export default defineComponent({
      setup() {
      const state = reactive<{
        articles: [Object]
      }>({
        articles: [{}],
      })
      const articles = computed(() => state.articles)
      const { $content } = useContext()
      state.articles = await $content('articles')
        .only(['title', 'description', 'img', 'slug', 'createdAt'])
        .sortBy('createdAt', 'desc')
        .fetch()
      return { articles }
      },
    })
  </script>

composables ディレクトリを作成して、ここに記事を操作する contetnCtl ファイルに API をまとめていきたいと思います。まずは記事一覧と記事情報を取得する API を実装したいと思います。

/composables/contentCtl.ts
import { reactive, computed, useContext } from '@nuxtjs/composition-api';
const contentCtl = () => {
  const state = reactive({
    articles: [] as Object,
    article: {} as Object,
  });
  const articles = computed(() => state.articles);
  const article = computed(() => state.article);
  const { $content } = useContext();
  async function getArticles() {
    state.articles = await $content('article')
      .only(['title', 'description', 'img', 'slug', 'updatedAt'])
      .sortBy('updatedAt', 'desc')
      .fetch();
  }
  async function getArticle(slug: string) {
    state.article = await $content('article'), slug).fetch();
  }
  return { article, articles, getArticle, getArticles };
};
export { contentCtl };

最終的にはこのファイルに記事を検索する処理をまとめていきたいと思います。

Articles.vue から記事一覧 処理の呼び出し

Articles コンポーネントから記事一覧を呼び出してみます。

/components/Articles.vue
  <tamlate>
    <div class="article-list">
      <div v-for="article of articles" :key="article.slug">
        <NuxtLink :to="{ name: 'blog-slug', params: { slug: article.slug } }">
          {{ article.title }}
        </NuxtLink>
      </div>
    </div>
  </template>
  <script lang="ts">
    import { defineComponent } from '@nuxtjs/composition-api';
    import { contentCtl } from '@/composables/contentCtl.ts';
    export default defineComponent({
      setup() {
        const { articles, getArticles } = contentCtl();
        return { articles};
      },
    });
  </script>

Articles 変数はリアクティブな変数ですので、処理が完了されたら画面に記事の一覧が表示されます。 同じ機能を色々な場所から読むような処理がある時にはコードもスッキリするかなと思います。これでやっと typescript でも中規模のものがやりやすくなってくるかなぁと感じます。