NuxtJSとTypescriptでStateのフォーマット化を共通実装!VueJSのテクニックを紹介します😎

NuxtJSとTypescriptでStateのフォーマット化を共通実装!VueJSのテクニックを紹介します😎

こんにちは!

最近は Typescript を使用したフロントエンド開発がデファクトスタンダードとなってきました。NuxtJS は VueJS をより開発しやすく、便利に扱える仕組みをいくつも搭載しています。NuxtJS は Typescript とも非常に相性が良いので、保守性高く開発を行うことが可能ですね。

本記事では、私たちが普段利用するテクニック「Vue.filter で State のフォーマット化共通実装」をご紹介します!

想定する読者

  • NuxtJS と VueJS で開発を行なっているヒト
  • VueJS で開発を行なっているヒト

はじめに

NuxtJS の Vue3 対応状況

NuxtJS は、Vue3のComposition API をアドオンで提供していますが、2021年7月現在、NuxtJS は Vue3 自体にはまだ非対応の様子です。しかし、それを差し引いても NuxtJS の数多くの VueJS 開発便利機能の提供と、SSR の実装しやすさは魅力的です。プロジェクトで SSR 要件がある場合はぜひ NuxtJS の導入を検討してみてください。対して、必ず Vue3 を利用したいといったプロジェクトの場合は、NuxtJS 導入は要検討です。

私たちの経験上、前述の通り NuxtJS は Vue3 の Composition API について はアドオンで利用できるので、SSR 要件があるのであれば開発効率の観点で NuxtJS を推奨します。

State のフォーマット共通実装テクニックの紹介😎

1. nuxt.config.js にプラグイン定義

Vue.filterを NuxtJS の Vue インスタンスにバインドさせるために、NuxtJS のプラグイン機能を活用します。

export default {
  ...
  plugins: [
    { src: '@/plugins/index.ts', mode: 'client' },
  ],
  ...
}

/plugins/index.ts の作成

Vue.filterを用途によって定義します。全ての Vue ファイルで共通利用するために、再利用可能な汎用的な名称・機能で作成することを推奨します。以下は実装例です。

import Vue from 'vue'
import moment from 'moment'
import {
  ProductCategory,
} from '~/graphql/API'

Vue.filter('displayDateTime', function (dateString?: string): string {
  if (!dateString) return ' - '
  return moment(dateString).format('YYYY年MM月DD日 HH:mm')
})

Vue.filter(
  'displayProductCategory',
  function (category?: ProductCategory): string {
    if (!category) return ' - '
    return {
      [ProductCategory.ConsumerElectronics]: '家電',
      [ProductCategory.HealthyFood]: '健康食品',
      [ProductCategory.Clothes]: '洋服',
      [ProductCategory.OfficeSupplies]: '事務用品',
    }[category]
  }
)

/graphql/API.ts

API の型情報(enum, type等)を定義します。Amplify が導入されているプロジェクトの場合、amplify codegenで作成するファイルとなります。

export enum ProductCategory {
  ConsumerElectronics = 'ConsumerElectronics',
  HealthyFood = 'HealthyFood',
  Clothes = 'Clothes',
  OfficeSupplies = 'OfficeSupplies',
}

2. Vue ファイルで利用

では、プラグインに定義したVue.filterを Vue ファイルで利用します。以下は簡易な商品詳細ページの例です。

<template>
  <div>
    <p>商品名:{{ product.name }}</p>
    <p>発売日:{{ product.publishedAt| displayDateTime }}</p>
    <p>カテゴリー:{{ product.category| displayProductCategory }}</p>
  </div>
</template>

上記の例のように、Vue.filter はパイプで値を渡すだけで簡単に利用することができます。

// JS部分
import { Vue, Component } from 'nuxt-property-decorator'
import { Context } from '@nuxt/types'
import { productStore } from '~/store'

@Component({
  async asyncData(context: Context) {
    const { store, route } = context
    await Promise.all([
      store.dispatch('productStore/getProductById', {
        Id: route.params.id
      }),
    ])
  },
})
export default class Index extends Vue {
  get product(){
    return productStore.getProduct
  }
}

実践では Vue.filter の定義が /plugins/index.ts に増えてきたら、Vue.filter を定義するファイルを分割することも検討してみてください。

私たちは、特に State の物理名を論理名に変換したい場合に積極的に利用しているテクニックとなります。

まとめ

各 Vue ファイルに State のフォーマット用の関数定義を行うのは、保守性・開発効率が悪化するので、ぜひ Vue.filter でフォーマット用の関数の共通実装を検討してみてください。

NuxtJS & VueJS、Typescript の開発は、お気軽にお問い合わせください。