俺、サービス売って家買うんだ

Swift, Kotlin, Vue.js, 統計, GCP / このペースで作ってればいつか2-3億で売れるのがポっと出来るんじゃなかろうか

Vue.jsのmixinを利用して肥大化したViewModelをリファクタリングする

f:id:ie-kau:20150818232251p:plain


今回はVue.jsのmixin機能を利用して肥大化したViewModelをリファクタリングするお話です。

肥大化してしまった例

Vue.jsを利用して画面全体をVMとして扱ことはよくあると思います。具体的には画面全体を囲むHTML要素のidををコンストラクタに渡すオブジェクトのelに設定することです。
下記の例では#js-appをelとして設定しています。

<div id="js-app" class="app">
  <div>野菜検索</div>
  <div>
    <input v-model="vegetableName" placeholder="野菜">
  </div>
  <button type="button" @click="searchVegetable">野菜を探す</button>
  
  <hr>

  <div>果物検索</div>
  <div>
    <input v-model="fruitsName" placeholder="果物">
  </div>
  <button type="button" @click="searchFruits">果物を探す</button>
</div>
new Vue({                                                                                                          
  el: '#js-app',
  data: {
    vegetableName: 'トマト',
    fruitsName: 'りんご'
  },
  methods: {
    searchVegetable() {
      alert('野菜を探す');
    },
    searchFruits() {
      alert('果物を探す');
    }
  }
});

この例では「野菜検索」と「果物検索」は相互に関係していないのにもかかわらず、それらのmethodsとdataが同じオブジェクトに含まれて初期化されていることが問題となってきます。
現状、そこまでコードの行数が多くないのですが複雑さが増してきた際に、複数の機能を一つのオブジェクトとして扱うと、どのメソッドやデータがどの機能(振る舞い)を管理しているかわかりにくくなってしまいます。

さらに、componentsとしてテンプレートを切り出すほどでもない・・・という悩みもでてきたりします。

そこでmixin

実は、Vue.jsにmixinを扱う機構がデフォルトで備わっています。そのためVMの中の一部の振る舞いを別オブジェクトとして外部に切り出してし初期化時にmixinとして埋め込むことができます。これは、mixinの本来の利用方法である汎用的な振る舞いの定義に利用できますし、今回のケースのように同一VM内での振る舞いの整理にも利用することができます。

JS部分を直してみる

こんな感じ。

  const VegetableSearchable = {
    data() {
      return {
        vegetableName: 'トマト'
      }
    },
    methods: {
        searchVegetable() {
        alert('野菜を探す');
      }
    }
  };
  
  const FruitsSearchable = {
    data() {
        return {
          fruitsName: 'りんご'
      }
    },
    methods: {
        searchFruits() {
        alert('果物を探す');
      }
    }
  }

  new Vue({
    el: '#js-app',
    mixins: [VegetableSearchable, FruitsSearchable]
  });

Vue mixins - JSFiddle

methodsやcreatedなどのライフサイクルを扱うメソッドにしか適用できないのかと勘違いしていましたが、data自体もmixinに閉じ込めることができるようです。
一VMでの機能が増えてきた際には是非導入していきたいところですね。

ヽ(•̀ω•́ )ゝ✧ オラッオラッ

参考

ミックスイン - vue.js

2015.03.02 訂正

ツイッターで以下のようなコメントを貰ったのでdataを関数に変更。データのスコープを閉じ込めるためですね。 ありがとうございます!

関連書籍

JavaScript フレームワーク入門

JavaScript フレームワーク入門