こんにちは、”はふぃ”です。

Vue.jsでFormのinput要素などに双方向データバインディングを作成する方法としてv-modelが存在します。

これを利用することでFormの更新はデータに反映され、データの更新はFormの表示に反映されます。

そこで今回は、v-modelを使ってstoreの情報を反映・更新する方法について書きます。

基本的な使い方

input要素やselect要素などのFormにv-modelを設定し、双方向にデータのやり取りを行います。

< sample.vue >

<template>
  <input v-model="message">
  <!-- 最初は'default message'が表示される -->
  <p>Message is: {{ message }}</p>
</template>

<script>
  export default {
    data () {
      return {
        message: 'default message'
      }
    },
    watch: {
      message (val) {
        // Formの値を更新するとデータが更新され、consoleにその値が出力される
        console.log(val)
      }
    }
  }
</script>

storeのデータとの連携

上記の例のように、クライアントに保存されているデータのやり取りやイベントのフックは簡単にできますが、storeに保存されたデータを反映させたり、storeのデータを更新するイベントのフックをv-modelで行うためには少し工夫が必要になります。

“ストア” は、基本的にアプリケーションの 状態(state) を保持するコンテナです。

https://vuex.vuejs.org/ja/guide/

サンプルとして、messageをstateに保存・mutationsで更新するstoreを準備します。

< storeSample.js >

const store = new Vuex.Store({
  state: {
    storeMessage: 'default message'
  },
  mutations: {
    updateMessage (state, val) {
      state.message = val
    }
  }
})

watchを使った方法

watchを使う場合には、Formとstoreでの値の更新をそれぞれ監視し、それをフックにもう片方の値を更新します。

Vue は Vue インスタンス上のデータの変更を監視し反応させることができる、より汎用的な 監視プロパティ(watched property) を提供しています。

https://jp.vuejs.org/v2/guide/computed.html#%E7%AE%97%E5%87%BA%E3%83%97%E3%83%AD%E3%83%91%E3%83%86%E3%82%A3-vs-%E7%9B%A3%E8%A6%96%E3%83%97%E3%83%AD%E3%83%91%E3%83%86%E3%82%A3

< watch.vue >

<template>
  <input v-model="message">
  <p>Message is: {{ message }}</p>
</template>

<script>
  import { mapState, mapMutations } from 'vuex'

  export default {
    data () {
      return {
        message: ''
      }
    },
    computed: {
      ...mapState([ 'storeMessage' ])
    },
    methods: {
      ...mapMutations([ 'updateMessage' ])
    },
    watch: {
      message (val) {
        this.updateMessage(val)
      },
      storeMessage (val) {
        this.message = val
      }
    },
    mounted () {
      this.message = this.storeMessage
    }
  }
</script>

しかし、この方法だとデータがどこで更新されているのか分かりづらく、処理が複雑になると視認性が悪くなります。そこで、このような場合には次のgetsetを利用した方法をオススメします!

getとsetを利用した方法

computedは基本的にgetter関数のみですが、setter関数を利用することもできます。これとv-modelを組み合わせることで上記の処理を分かりやすく表現することが可能です。

< getterAndSetterSmaple.vue >

<template>
  <input v-model="message">
  <p>Message is: {{ message }}</p>
</template>

<script>
  import { mapMutations } from 'vuex'

  export default {
    computed: {
      message: {
        get () {
          return this.$store.state.message
        },
        set (val) {
          this.updateMessage(val)
        }
      }
    },
    methods: {
      ...mapMutations([ 'updateMessage' ])
    }
  }
</script>

まとめ

computedのsetter関数はこの利用方法で初めて使いました。

実は便利だったりするシーンもあると思うので、頭に入れておくと良いかもしれません。

投稿者: はふぃ

若手のWEBフロントエンジニア。最近はバレーボールにハマってます!

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA