Vue.jsでEnumのようなモノを作る


概要

javascriptにはEnum(列挙型)がありません。
ですが、SinglePageApplicationだとサーバーサイドで持っている列挙型の定義を
フロントエンド側でも使いたい場合があるので、Enumもどきを作ってみました。

前提

Vue.jsで作られたアプリケーション内でEnumを使いたいと考えています。
なので、

App.vue
<template>
<div>
  <!-- 男性 -->
  <p>{{Enum.EnumSex.Male}}</p>
</div>
</template>

といった使い方を想定します。
TypeScriptにすれば列挙型を使うことができるのですが、
Vue.jsのTypescript化はなんかすごい大変なので・・・・割愛します。
またの機会に。

詳細

Enumもどきのオブジェクト

javascriptで列挙型を実現するにはObjectを使うしかありません。
前述の例だと

sample
var EnumSex = {
  Male:"男性",
  Female:"女性"
}

という形で定義することができます。
ただ、これだとシステム的に「男性=1」「女性=2」といったコード定義を
判定することはできません。なので、さらにObjectを入れ子にして、
定義と表示用文字列を分けてみます。

sample
const EnumSex = {
  Male:{
    val:1,
    text:"男性"
  },
  Female:{
    val:2,
    text:"女性"
  }
}

これであれば

sample
EnumSex.Male.text //男性

と表現できます。

import用ファイルにまとめ

定義しただけだと、Vue.jsのコンポーネント内で使えないので、
importしていく必要があります。
importするためのファイルを下記のように作成します。

Enum.js
//商品一覧並び順
export const EnumItemListSort = {
  //価格の昇順
  PriceLowestFirst : {
    val:"1",
    text:"金額が安い順"
  }, 
  //新着順
  NewestFirst : {
    val:"2",
    text:"新着順"
  }
} 
//性別
export const EnumSex = {
  Male:{
    val:1,
    text:"男性"
  },
  Female:{
    val:2,
    text:"女性"
  }
}

列挙型は基本的に後から変更をしないのでconstで定義します。
同一ファイル内にexportで定義をしておきます。
export defaultだと任意の1つしか読み込まれないので注意ください。

Vue.js単一ファイルコンポーネントへの読み込み

単一ファイルコンポーネント内でimportします。

App.vue
<template>
  <div>
<input type="radio" name="sex" :value="refEnum.EnumSex.Male.val">{{refEnum.EnumSex.Male.text}}
<input type="radio" name="sex" :value="refEnum.EnumSex.Female.val">{{refEnum.EnumSex.Female.text}}
  </div>
</template>

<script>
import * as Enum from '@/lib/definition/enum';
export default {
  name: 'sample',
  data: function(){
    return {
      //data内ではEnumの直接参照が可能
      hoge:Enum.EnumSex.Male.val
    }
  },
  computed:{
    //template内ではcomputedを介する必要がある
    refEnum:()=>Enum,
  }
}
</script>
<style scoped>
</style>

基本的にはimportするだけでいけますが、template内で使う場合は、
importしたものを直接利用することはできないので、一旦computedに別変数で格納して、
その変数経由で参照する必要があります。めんどくさいですね。

あとがき

思った以上に列挙型っぽいことをさせるのが面倒で、いっそTypescript化したほうが
早いんじゃないか・・・とやってる最中におもったりもしました。
次は頑張ってvue-class-componentについてまとめたい次第です