【Nuxt】nuxt-propety-decoratorの使い方を基礎の基礎で勉強する

あるあるの参考を使って、nuxt-propety-decoratorを体系的に理解していく。

2023年01月14日
関連記事

導入

nuxt-property-decoratorはvue-property-decoratorのラッパーです。
ハンズオン形式で実践していきましょう。
nuxt × typescript で開発を進めていく方におすすめ(というかメタプログラミングに役に立つ機能です)
今回は開発しやすくなるようにと取り入れてみます。

あらかじめ、とてもわかりやすい記事を見つけたので、参考に載せておきます

せっかくなので、前回のプロジェクトに実装していきます。

準備

以下のコマンドを入力し、nuxt-property-decoratorを入れていきます。
$ yarn add nuxt-property-decorator

まず、今のプロジェクトに不要なものを削除していきます。(Vuetifyに依存するものあり)

$ rm components/NuxtLogo.vue
$ rm components/Tutorial.vue
$ rm components/VuetifyLogo.vue
$ rm pages/inspire.vue

Vuetifyのdarkモードが煩わしいので nuxt.config.js を変更

export default {
    ~~~
  vuetify: {
    customVariables: ['~/assets/variables.scss'],
    theme: {
      // dark: true,
      themes: {
        dark: {
          primary: colors.blue.darken2,
          accent: colors.grey.darken3,
          secondary: colors.amber.darken3,
          info: colors.teal.lighten1,
          warning: colors.amber.base,
          error: colors.deepOrange.accent4,
          success: colors.green.accent3
        }
      }
    }
  }
    ~~~
}

headerも必要ないので消しましょう
ついでに nuxt-property-decorator で書き換えます。
layouts/default.vue

<template>
</template>

<script>
import { Component, Vue } from 'nuxt-property-decorator'

@Component
export default class DefaultLayout extends Vue {}
</script>

実際に作りながら覚える

体系的に覚えていきましょう。
初学者の参考によくある、ボタンを押してインクリメントしていくタイプの機能を作っていきます。

実装

以下のコマンドを実行し、クリック -> 文字数をカウントしていくコンポーネントを作成
$ touch components/Count.vue

各ページを真似て実装してみてください

components/Count.vue

<template>
  <v-btn @click="increments">
    <span>{{ counter }}</span>
  </v-btn>
</template>

<script lang="ts">
import { Component, Prop, Emit, Vue } from 'nuxt-property-decorator'

@Component
export default class Count extends Vue {
  @Prop({ type: Number, default: 0 }) counter!: number

  @Emit()
  increments(): number {
    return this.counter
  }
}
</script>

pages/index.vue

<template>
  <count :counter="counter" @increments="increments"></count>
</template>

<script lang="ts">
import { Component, Vue } from 'nuxt-property-decorator'
import Count from '~/components/Count.vue';

@Component({
  components: {Count}
})
export default class Index extends Vue {
  counter: number = 0

  increments(): void {
    this.counter++
  }
}
</script>

ボタンを押すごとにイベントを通知するcountコンポーネントを作り、親のindex.vueに伝達するロジックです。

実際に動かし、文字数がカウントアップされることを確認してください。

応用してみる

せっかくcountコンポーネントとして共通化したので、複数似たような機能を作ってみましょう。

イメージとしては、アルバイトでたまにある

  1. 横断歩道で歩行者が通った回数
  2. 横断歩道で自転車が通った回数
  3. 横断歩道を自動車が通った回数

をカウントしていくプログラムです。
修正点としては以下です。

  • countコンポーネントにnameプロパティを追加
  • ボタンに名前をつける
  • 呼び出し元のindex.vueで、各カウンターを複数置く

components/Count.vue

<template>
  <v-btn @click="increments">
    <span>{{ name }}: {{ counter }}回</span>
  </v-btn>
</template>

<script lang="ts">
import { Component, Prop, Emit, Vue } from 'nuxt-property-decorator'

@Component
export default class Count extends Vue {
  @Prop({ type: String }) name!: string
  @Prop({ type: Number, default: 0 }) counter!: number

  @Emit()
  increments(): number {
    return this.counter
  }
}
</script>

pages/index.vue

<template>
  <div>
    <count name="歩行者" :counter="walker" @increments="walker++"></count>
    <count name="自転車" :counter="cycle" @increments="cycle++"></count>
    <count name="自動車" :counter="car" @increments="car++"></count>
  </div>
</template>

<script lang="ts">
import { Component, Vue } from 'nuxt-property-decorator'
import Count from '~/components/Count.vue';

@Component({
  components: { Count }
})
export default class Index extends Vue {
  walker: number = 0
  cycle: number = 0
  car: number = 0
}
</script>

実際に動かして確認してみましょう。
++--に置き換えるとデクリメントになりますので、応用として試してみてください。

@Component

@Conponentに指定できるパラメータはcomponents, directives, filters, mixins, middleware, lauoutsです。
※ 他にもあるかも
規模的に今回はcomponentsのみで実装していきます。

@Prop

Vueでも馴染みのあるpropsとして理解していきましょう。
親コンポーネントから子コンポーネントへ、定義したメンバー名でpropsを指定できます。
今回の実装では、横断歩道で歩行者が通った回数(walker), 横断歩道で自転車が通った回数(cycle), 横断歩道を自動車が通った回数(car)の各変数を子コンポーネントとへ渡しています。

@Emit

コンポーネント間での値をEmitにより伝達します。
今回の実装では、子コンポーネントから「ボタンをクリックしたよ!!」を親コンポーネントに伝えるために使っています。
通知を受け取る親コンポーネントでは @increments="walker++" などのように、各変数に1を足す仕組みです。

共有

【今回の作業ブランチ】
https://github.com/yutahhh/firebase-study/tree/feature/%232

【Hosting】
https://fir-study-42747.web.app/

お疲れ様でした。
超初歩的な内容でしたが、初学者のためになれば幸いです。

筆者情報
IT業界経験6年目のフルスタックエンジニア。
フロントエンドを軸として技術を研鑽中でございます。