0%

Programmingプログラミングナレッジ

Posted:2019.06.13

v-modelでstateやgettersを変更したい時に使える算出プロパティのset()関数

フォームなどに入力した値がリアルタイムで変数と同期される双方向バインディングはVueの強みの一つでもあります。ただし、変数にstateを使った場合には仕様上、直接更新することができません。そこで今回はv-modelでstateを更新する方法についてまとめていきたいと思います。

 

v-modelを使った双方向バインディングの基本形

まずはVueで扱う双方向バインディングの基本からおさらいです。過去記事「Vue.jsで双方向データバインドを使ったサンプル」にもまとめておりますのでご参考に。

 

この双方向バインディングは、対象となる入力要素(inputなど)に「v-model」ディレクティブを設定し、その値に変数や関数を指定します。出力側では2重波括弧のマスタッシュ( {{ }} )でv-modelで指定した変数もしくは関数を囲みます。

【Vue】

<template>
 <div id="app">
  <input type="text" v-model="messege">
  <p>入力:{{ messege }}</p> 
 </div>
</template>

<script>
 export default {
  data: function() {
   return {
    messege: 'default'
   }
  }
 }
</script>

 

上記では、dataオプションで指定した変数の値がinputで入力した内容と同期される形になります。これが基本的な双方向バインディングの形となります。実際に実装した例を見るとこのような形になります。

v-modelでstateやgettersを変更したい時に使える算出プロパティのset()関数

 

テキストを入力すると出力側でも値が更新されるのが確認できます。

v-modelでstateやgettersを変更したい時に使える算出プロパティのset()関数

 

しかし、下記のように変数にstateを参照する場合、v-modelで更新しようとするとエラーになってしまいます。これはVueの仕様でstateの値はmutationsからのみ更新できるというルールに基づいているためです。

v-modelでstateやgettersを変更したい時に使える算出プロパティのset()関数

 

実際にstateの値も更新されていないのが確認できます。

v-modelでstateやgettersを変更したい時に使える算出プロパティのset()関数

 

そこで、v-modelでstateの値を更新する方法をいくつか見ていきましょう。

 

v-onとdispatch()関数を使ったv-modelでのstateの更新

v-modelでstateの値を更新する方法の1つに、v-onのイベントハンドラで「dispatch()」関数でactionsを呼び出したり「commit()」関数でmutationsを呼び出すことによりstateを更新する方法があります。まずは下記のようにstateやactions、mutationsを定義していきます。

【store.js】

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
 state: {
  messege: 'default' // stateの初期値
 },
 mutations: {
  mutateMessege(state, payload) {
   state.messege = payload;
  }
 },
 actions: {
  commitMessege(store, payload) {
   return store.commit('mutateMessege', payload)
  }
 },
 getters: {
  getStateMessege: (state) => state.messege
 }
})

 

stateには初期値を、mutationsにはstateの値を引数である「payload」によって更新されるように、actionsには引数である「payload」を受け取りmutationsに渡すための関数を指定します。stateの値はgettersで取得できるようにしておきます。詳しくはこちらの記事「stateの値を参照するときに使えるgettersについて」を参考に。

 

そして、Vueファイルの方でロジックを記述していきます。まずテンプレート側の入力要素にはv-modelディレクティブにdataオプションの変数を指定します。そしてv-onディレクティブでイベントを設定し、発火させる関数を指定します。ここではinputイベントで設定しています。必要であれば出力させる要素も用意しておきます。

【Vue】

<template>
 <div id="app">
  <textarea v-model="messege" @input="inputText">
  </textarea>
  <p>入力:{{ messege }}</p>
  <p>stateの値:{{ computedGetState }}</p>
 </div>
</template>

<script>
 export default {
  data: function() {
   return {
    messege: 'default'
   }
  },
  computed: {
   computedGetState() {
    return this.$store.getters.getStateMessege
   }
  },
  methods: {
   inputText() {
    // dispatch()でactionsを呼び出す、もしくはcommit()で直接mutationsを呼び出す
    this.$store.dispatch('commitMessege', this.messege)
   }
  }
 }
</script>

 

スクリプトの方では、変数をdataオプションで用意します。そしてmethodsではイベントハンドラに設定した関数を記述します。この関数内で、v-modelで指定した変数を「dispatch()」関数で定義したactionsを呼び出す形になります。dispatchの第一引数には呼び出すactionsの関数を、第二引数には受け取る変数を指定します。ちなみにactionsを経由せずに「commit()」関数で直接mutationsを呼び出してもOKです。

 

これでv-modelとstateが紐づけられ、双方向バインディングが実装することができました。実際のサンプルを見ていきます。デフォルトではそれぞれの初期値が表示されています。

v-modelでstateやgettersを変更したい時に使える算出プロパティのset()関数

 

値を入力すると、mutationsを経由して、stateの値が更新されているのが確認できますね。

v-modelでstateやgettersを変更したい時に使える算出プロパティのset()関数

 

 

算出プロパティのset()関数を使ったv-modelでのstateの更新

先ほどのイベントハンドラを使った方法でも実装は可能ですが、少し冗長性が感じられてしまいます。そこで算出プロパティの「set()」関数を使ってよりシンプルに実装する方法についてまとめていきたいと思います。actions、mutationsなどの定義は先程と同じなのですが、Vueの方ではよりすっきりと短いコードになります。

【Vue】

<template>
 <div id="app">
  <textarea v-model="computedGetState">
  </textarea>
  <p>入力:{{ computedGetState }}</p>
  <p>stateの値:{{ computedGetState }}</p>
 </div>
</template>

<script>
 export default {
  computed: {
   computedGetState: {
    get() {
     // 値を返すときはgettersを指定
     return this.$store.getters.getStateMessege
    },
    set(value) {
     // 値の代入はdispatch()でactionsを呼び出す、もしくはcommit()で直接mutationsを呼び出す
     this.$store.dispatch('commitMessege', value)
    }
   }
  }
 }
</script>

 

まず、テンプレート側ではv-modelに算出プロパティのcomputedで定義した関数のオブジェクトのキーを指定します。出力する要素にも同じものでOKです。先ほどのものと比べてもかなりスッキリとしましたね。

 

スクリプト側では、テンプレートで指定したオブジェクトをcomputedに用意していきます。ここで「get()」関数と「set()」関数の2つを用意します。

 

まず、get()関数の方には、そのままgettersが返されるようにしておきます。つまり、出力される場合はgettersの値が表示されるようになります。

 

そして、set()関数には引数を受けてdispatch()もしくはcommit()関数でactionsやmutationsを経由してstateの値を更新するようにしておきます。つまり、値が入力されて代入する場合にはその値を受け取りstateが更新される仕組みです。ですので、set()関数には引数が必要になります。この引数にはv-modelで関連づけられた入力要素の入力値が入ります。

 

実際のサンプルを見ていきます。算出プロパティにあるgettersが初期値に表示されています。

v-modelでstateやgettersを変更したい時に使える算出プロパティのset()関数

 

入力すると双方向バインディングにより、入力値が同期され、stateにはmutations経由で値が更新され、出力側にはgettersで更新されたstateの値が表示されています。

v-modelでstateやgettersを変更したい時に使える算出プロパティのset()関数

v-modelでstateやgettersを変更したい時に使える算出プロパティのset()関数

 


 

いかがでしょうか、双方向バインディングにおいては実装ケースも多いかと思いますが、stateの値を扱う場合には少し注意が必要ですね。その場合には上記の方法がとても役に立つのではないでしょうか。

author
この記事を書いた人オガワ シンヤ
FacebookTwitter

DesignSupply.代表 / ディレクター・ウェブデザイナー・フロントエンドエンジニアをやっています。「ウェブとデザインでヒト・モノ・サービスを繋げ新しい価値を生み出す」をコンセプトに日々奮闘中!制作中はチョコレートが欠かせない三十路Webクリエイター。

制作のご依頼やお問い合わせ・パートナー業務提携のご相談はこちら

デザインやウェブ制作についてのご依頼やご相談、その他お問い合わせなどもお気軽にご連絡ください。フットワークの軽さやレスポンスの早さ、また豊富な経験や知識、技術を活かした対応力といったフリーランスクリエイターの強みでクライアント様、パートナー企業様のお力になります。デザインからコーディングやWordPress実装といったウェブサイト構築はもちろん、写真撮影や動画編集、コンテンツ制作からサイト運用サポートまで一括してお任せください。

ホームページ制作のご検討やウェブ運用でお悩みの経営者様や企業のウェブ担当者様をはじめ、個人で店舗を営んでいらっしゃるオーナー様、フリーで活動されているビジネスオーナー様はもちろんのこと、リソース不足でお困りの制作会社様、またクリエイターをお探しの代理店様も大歓迎です。

コンタクトをご希望の方はお手数ですが、下記よりお問い合わせフォームのページへアクセスしていただき、必要事項を入力の上メッセージを送信してください。確認でき次第すぐに折り返しご連絡致します。

こんな記事も読まれています

コメントもお気軽にどうぞ

記事に関するご質問やご意見などありましたら下記のコメントフォームよりお気軽に投稿ください。なおメールアドレスは公開されませんのでご安心ください。また、* が付いている欄は必須項目となります。

内容に問題なければ、下記の「コメントを送信する」ボタンを押してください。

CAPTCHA


ページトップへ