nanisore oishisou

Webエンジニアあるまさんのゆるふわ奮闘記。

v-modelをちゃんと理解し、Vue-select+Vuexで実装する方法、そして好みの引数を渡す方法

あなたは覚えているだろうか。この記事を。

arm4.hatenablog.com

そう。Vuexを導入するとv-modelは使えなくなる。

これは、v-modelではstoreのstateを直接書き換えに行ってしまうためだ。
そのため、上記のようにして自前でstateの値と同期が取れるように書いてやる必要性がある。

ライブラリを導入しようと思うと、だいたいサンプルのコードにはv-modelが登場してくるので
Vuex初心者は困惑してしまう。

これも、上記のv-modelとは要するに何をしているのかということを理解することで ライブラリのサンプルのコードを自前で書き直すことができるようになる。

v-modelとはつまり何か

まずはこちらのv-modelについての公式の解説を見てもらいたい。

jp.vuejs.org

<input v-model="searchText">

イコール

<input
  v-bind:value="searchText"
  v-on:input="searchText = $event.target.value"
>

この原理を利用してVuexのstoreのステートをセットするようにしているのが、
私が前に書いた記事の手法である。

それからライブラリに登場する際のv-modelを理解するのに重要なのが、以下の部分。

<custom-input
  v-bind:value="searchText"
  v-on:input="searchText = $event"
></custom-input>
Vue.component('custom-input', {
  props: ['value'],
  template: `
    <input
      v-bind:value="value"
      v-on:input="$emit('input', $event.target.value)"
    >
  `
})

要するにカスタムコンポーネントを使っている場合の挙動はこちらになる。

ここでたぶんみんな思うことは一つだと思う。

searchTextに代入している$eventとは一体何ですか?

jp.vuejs.org

コンポーネントでイベントをリッスンすると、送出されたイベントの値に $event でアクセスできます:

要するに子コンポーネントでinputというカスタムイベントを発行し、
そこで本当のネイティブイベントのvalueを親に渡しているということだ。

Vue-selectはカスタムコンポーネントで実現されているので、
この挙動を理解することで自分が意図したように実装することができる。

Vue-selectって何?

sagalbot.github.io

要するにVue版のSelect2だ。

Vue-select+Vuexの実装方法

Vuexを使っている際の実装方法は実は公式ドキュメントに記載がある。

Vuex · vue-select

このような実装だと、毎度毎度setActivePersonのようなメソッドを書かなくてはいけなくなるので
できれば私が書いた記事のようにkey_nameを渡したら勝手にsetしてくれるような汎用的なメソッドを通したいところだ。

そのためには、key_nameを渡すようにしたいが、
引数を渡すとvalueが渡されてこない。

ここにkey_nameを渡すには、仕組みが分かっていないと渡せない。

ここでさっきの知識が生きてくる。

Vue-selectは、選択された値が変わるとon-changeというプロパティに設定したcallback関数が実行される仕組みになっている。

github.com

デフォルトでは以下が設定されている。

      onChange: {
        type: Function,
        default: function (val) {
          this.$emit('input', val)
        }
      },

自前のinputカスタムイベントを発火することで、v-modelを使ってデータが同期されるようにしているようだ。

公式サイトに書いてあったカスタムコンポーネントの作り方と同じ手法だ。

ここでもう一度v-onのおさらいをする。

jp.vuejs.org

通常の要素上で利用した場合、ネイティブ DOM イベント だけ購読します。カスタム要素コンポーネント上で利用した場合、子コンポーネント上での カスタムイベント の発行を購読します。

ということで、inputタグで@inputとするのとv-selectタグで@inputと書くのは
もともと全然意味が違う。

@inputでVue-selectが発行しているカスタムイベントをリッスンし、$eventでそのイベントが渡してくるデータを拾う。

<v-select 
    multiple
    label="email"
    @input="updateValue($event, 'active_peaple')"
    :options="$store.state.people"
    :value="$store.state.form.active_peaple"
  ></v-select>

このようにすると、思い通りkey_nameが渡せるようになる。

実際に実装してみたコードは以下だ。

codepen.io

v-modelとカスタムコンポーネントの仕組みを理解することで、
カスタムコンポーネントとして実装するタイプのコンポーネントをVuexで思い通りに実装するやり方が分かるようになると思う。

これからVuexやるよって人は、 難しいと思わずにしっかり抑えておいて欲しい!