Nuxt.jsで列挙型を使う(with vue-property-decorator)

2020.10.11

はじめに

vue-property-decoratorを使ってNuxt.jsアプリケーションを作る際に、列挙型を設定したくなったのですが、まだ経験はなかったので、どこにどんなことを書けばいいんだっけ?というのを調べつつ、自分への備忘録も兼ねて記事化しました。

別記事で作成したサンプルアプリケーションに対して、姓名の他に血液型を追加し、血液型がABO式の値(「A」「B」「O」「AB」)しか指定できないように列挙型に設定を行ってみた、という内容になりまます。

やってみたこと

実施内容

$ vim models/definitions.ts
$ vim components/TestComponent.vue
$ vim pages/index.vue

models/definitions.ts

// ABO式を利用する
export enum BloodType {
  TYPE_A = "A",
  TYPE_B = "B",
  TYPE_O = "O",
  TYPE_AB = "AB"
}

export interface User {
  firstName: string
  lastName: string
  bloodType: BloodType
}

components/TestComponent.vue

<template>
  <div>
    Name: {{ fullName }}
    Message: {{ message }}
    BloodType: {{ bloodType }}
  </div>
</template>

<script lang="ts">
import { Vue, Component, Prop } from 'vue-property-decorator'
import { BloodType, User } from "../models/definitions";

@Component
export default class TestComponent extends Vue {
  @Prop({ type: Object, required: true }) readonly user!: User

  message: string = 'This is a message'

  get fullName (): string {
    return `${this.user.firstName} ${this.user.lastName}`
  }

  get bloodType (): BloodType{
    return this.user.bloodType
  }
}
</script>

pages/index.vue

<template>
<div>
  <h1>This is Test</h1>
  <TestComponent :user="testUser" />
</div>
</template>

<script lang="ts">
import { Component, Vue } from "vue-property-decorator";
import { BloodType, User } from "../models/definitions";
import TestComponent from "~/components/TestComponent.vue";

@Component({
  components: {
    TestComponent,
  },
})
export default class IndexPage extends Vue {
  myname:User = {
      firstName: "aki",
      lastName: "kato",
      bloodType: BloodType.TYPE_AB
    }
  get testUser(){
    return this.myname
  }
}
</script>

画面表示

説明

models/definitions.ts について

index.vueとTestComponent.vueの間に、Userオブジェクトを利用する場合には

  • bloodTypeの指定が可能
  • bloodTypeはA・B・O・ABのみ指定可能

という制約をこのモジュールを通して作るために、BloodTypeという列挙型とUserというインターフェースを定義しました。

components/TestComponent.vue について

以前別記事で作成したものに対して、 definitions.ts のインポートと bloodType を算出プロパティ経由で画面表示する部分を追加しました。

before.vue

<template>
  <div>
    Name: {{ fullName }}
    Message: {{ message }}
  </div>
</template>

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

interface User {
  firstName: string
  lastName: string
}

@Component
export default class TestComponent extends Vue {
  @Prop({ type: Object, required: true }) readonly user!: User

  message: string = 'This is a message'

  get fullName (): string {
    return `${this.user.firstName} ${this.user.lastName}`
  }
}
</script>

after.vue

<template>
  <div>
    Name: {{ fullName }}
    Message: {{ message }}
    BloodType: {{ bloodType }}
  </div>
</template>

<script lang="ts">
import { Vue, Component, Prop } from 'vue-property-decorator'
import { BloodType, User } from "../models/definitions";

@Component
export default class TestComponent extends Vue {
  @Prop({ type: Object, required: true }) readonly user!: User

  message: string = 'This is a message'

  get fullName (): string {
    return `${this.user.firstName} ${this.user.lastName}`
  }

  get bloodType (): BloodType{
    return this.user.bloodType
  }
}
</script>
pages/index.vue について

TestComponent.vue と同様に definitions.ts のインポートと bloodType を算出プロパティ経由で画面表示する部分を追加しました。

before.vue

<template>
<div>
  <h1>This is Test</h1>
  <TestComponent :user="testUser" />
</div>
</template>

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

@Component({
  components: {
    TestComponent,
  },
})
export default class IndexPage extends Vue {
  myname = {
      firstName: "aki",
      lastName: "kato"
    }
  get testUser(){
    return this.myname
  }
}
</script>

after.vue

<template>
<div>
  <h1>This is Test</h1>
  <TestComponent :user="testUser" />
</div>
</template>

<script lang="ts">
import { Component, Vue } from "vue-property-decorator";
import { BloodType, User } from "../models/definitions";
import TestComponent from "~/components/TestComponent.vue";

@Component({
  components: {
    TestComponent,
  },
})
export default class IndexPage extends Vue {
  myname:User = {
      firstName: "aki",
      lastName: "kato",
      bloodType: BloodType.TYPE_AB
    }
  get testUser(){
    return this.myname
  }
}
</script>

おわりに

vue-property-decoratorを使って列挙型を作成する上でかなりミニマムなものを作成できたと思います。今後やり方をど忘れしたときに参考にしたいと思います。 その他、どなたかの参考になれば幸いです。