📗

Nuxt.js+Vuetify+axiosで外部APIから取得した情報を表示するまで

2022/01/20に公開

Nuxt.jsのプロジェクトでaxiosを使ってAPIから情報を取ってきた情報をVuetifyで表示する。

完成イメージ

Zenn Trend APIで取得した情報を一覧として表示する。

プロジェクト作成

  1. create-nuxt-appを使ってプロジェクト作成をする。
  2. composition-apiとdate-fnsをインストールする。
npm install -g yarn
yarn add nuxt
yarn create nuxt-app nuxt_vuetify_sample
cd nuxt_vuetify_sample
yarn add --dev @nuxtjs/composition-api
yarn add --dev @nuxtjs/date-fns

参考

https://github.com/nuxt/create-nuxt-app

実装

見やすさ重視でソースは1つにしたが、実際の開発では色々切り分けた方が良いと思う。

zennTechTrendList.vue
<template>
  <div>
    <h1>Zennトレンド一覧(Tech)</h1>
    <v-data-table
      :headers="headers"
      :items="state.articles"
      :items-per-page="5"
      class="elevation-1"
    >
      <template #[`item.publishedAt`]="{ item }">
        {{ $dateFns.format(item.publishedAt, 'yyyy-MM-dd HH:mm:ss') }}
      </template>
    </v-data-table>
  </div>
</template>

<script lang="ts">
import {
  defineComponent,
  reactive,
  useContext,
  onMounted,
} from '@nuxtjs/composition-api'

type Article = {
  title: string
  likedCount: number
  publishedAt: string
}

type State = {
  articles: Article[]
}

export default defineComponent({
  setup() {
    const headers = [
      { text: '記事名', value: 'title' },
      { text: 'いいね数', value: 'likedCount' },
      { text: '公開日時', value: 'publishedAt' },
    ]
    const state = reactive<State>({
      articles: [],
    })
    const { $axios } = useContext()
    const getZennArticles = async () => {
      const url = 'https://zenn-api.netlify.app/.netlify/functions/trendTech'
      const response = await $axios.$get<Article[]>(url)
      state.articles = response
    }
    onMounted(() => {
      getZennArticles()
    })
    return { headers, state }
  },
})
</script>

import・定義

Composition APIで使用するもののみインポートする。表示する記事情報にArticleとして定義する。また、Articleは複数取得するので、Stateで配列として扱う。

import {
  defineComponent,
  reactive,
  useContext,
  onMounted,
} from '@nuxtjs/composition-api'

type Article = {
  title: string
  likedCount: number
  publishedAt: string
}

type State = {
  articles: Article[]
}

defineComponent

Vue コンポーネントオブション中でTypeScriptに型を推論してもらうためにdefineComponent内で色々書く。

  • headers:テーブルのヘッダー
  • state:外部APIから取得した記事情報。
  • $axios:外部APIと通信するもの。
  • getZennArticles:外部APIと通信してstateに記事の情報を入れる関数。

headersとsteteをreturnするとtemplate内で使用できるようになる。

export default defineComponent({
  setup() {
    const headers = [
      { text: '記事名', value: 'title' },
      { text: 'いいね数', value: 'likedCount' },
      { text: '公開日時', value: 'publishedAt' },
    ]
    const state = reactive<State>({
      articles: [],
    })
    const { $axios } = useContext()
    const getZennArticles = async () => {
      const url = 'https://zenn-api.netlify.app/.netlify/functions/trendTech'
      const response = await $axios.$get<Article[]>(url)
      state.articles = response
      return response
    }
    onMounted(() => {
      getZennArticles()
    })
    return { headers, state }
  },
})

参考

https://v3.ja.vuejs.org/api/composition-api.html

Vuetify

Vuetifyを使用して、記事一覧を作成する。
今回は「v-data-table」を使用する。

v-data-table

  • headers:defineComponentで設定したheadersが適用される。
  • items:defineComponentで設定したstateのうちarticlesが適用される。
  • items-per-page:1ページあたりの記事の表示数。デフォルトは10。
  • elevation-1:コンポーネントの高さを設定。数値によってテーブルが浮く。

v-data-tableはitem.<name> を使用すると、特定の列のみをカスタマイズできるので、publishedAtは「yyyy-MM-dd HH:mm:ss」に変換する。変換処理にはdate-fnsを使用する。

<template>
  <div>
    <h1>Zennトレンド一覧(Tech)</h1>
    <v-data-table
      :headers="headers"
      :items="state.articles"
      :items-per-page="5"
      class="elevation-1"
    >
      <template #[`item.publishedAt`]="{ item }">
        {{ $dateFns.format(item.publishedAt, 'yyyy-MM-dd HH:mm:ss') }}
      </template>
    </v-data-table>
  </div>
</template>

参考

https://vuetifyjs.com/ja/components/data-tables/
https://vuetifyjs.com/ja/styles/elevation/
https://www.npmjs.com/package/@nuxtjs/date-fns

Discussion