Vue.js で表示したデータの更新とイベント処理

更新日
2017.08.28
作成日
2017.02.12

Vue.js を使って表示したデータをイベントを使って更新します。

自分で要素を更新しなくても良い

データ(変数)が更新されたら自動的に DOM も更新され、逆に項目選択やフォーム入力値などで値が更新されたらデータも更新されるというように今まで自分で書いていた処理を Vue がしてくれます。

ちなみに私が JavaScript のフレームワークをどれかやってみたいと思った一番の理由がこの機能が便利そうだったからです。自動的にセッターとゲッターを登録して変更を監視してくれます。

イベント処理を登録する

先にイベントについて簡単に説明。

「要素にマウスが乗った時」「ボタンをクリックした時」などの イベント を利用するには v-on ディレクティブを使います。v-on@で省略が可能です。jQuery の on と似てます。

<button v-on:click="処理内容やメソッド名">click!</button>

省略した書き方。v-bind と同じで最初のうちは v-on で書いて慣れてきたら省略するのがオススメ。

<button @click="処理内容やメソッド名">click!</button>

修飾子を使えば JavaScript でよく使う event.preventDefault() などの指定もできます。

<button @click.prevent="処理内容やメソッド名">click!</button>

単純なテキストを更新する

普通のテキストを更新してみましょう。以下はボタンをクリックすると methods に登録してある test1 を実行します。処理はデータにある count の数を増やします。表示している場所も変えないといけないから要素を探して~みたいな事はしていません(๑'ᴗ'๑)

<p>あなたは{{ count }}回クリックしたよ</p>
<button @click="test1">click!</button>

jQuery のようにテキストを要素で囲む必要もありません。

var vm = new Vue({
 el: '#app',
 data: {
  count: 0
 },
 methods: {
  test1: function() {
   this.count++
  }
 }
})

値には式が使えるので使いまわす予定のない短いコードならメソッドを用意しないで直接式を書くことも出来ます。

<button @click="count++">click!</button>

リストのデータを更新する

配列を更新

リストの一部のインデックス 0 の「りんご」のデータを更新してみます。

<ul>
 <li v-for="val in test2list">{{ val }}</li>
</ul>
<button @click="test2">click!</button>
var vm = new Vue({
 el: '#app',
 data: {
  test2list: ['りんご', 'ばなな', 'いちご']
 },
 methods: {
  test2: function() {
   this.test2list[0] = 'もぐもぐ'
  }
 }
})

何も考えずにこう書いてみたけどこれは出来ないみたいです。参考

参考 URL を読むと、JavaScript の制限で配列は直接変更出来ないから内容が変わった事を Vue が察知できるように $set メソッドを使ってねーという事です。多分セッターが使用できるのは対象がオブジェクトの場合だけだから?

vm.$set(object, key, value)

上のデータに置き換えるとこんな感じですね。メソッドの内容を書き直します。

this.$set(this.test2list, 0, 'もぐもぐ')

今度はちゃんと更新されましたね。

オブジェクトを更新

オブジェクトは特に滞りなく変更できました。

<ul>
 <li v-for="(val, key) in test4list">(Key:{{ key }}) {{ val }}</li>
</ul>
<button @click="test4">click!</button>
var vm = new Vue({
 el: '#app',
 data: {
  test4list: {
   'a': 'ハンバーグ',
   'b': '焼肉',
   'c': 'パスタ'
  }
 },
 methods: {
  test4: function() {
   this.test4list.a = 'もぐもぐ'
  }
 }
})

オブジェクトのリストを更新

また配列なのですがとりあえず $set を使わずに試してみます。

<ul>
 <li v-for="(val, no) in test5list" v-bind:key="val.name">
  (No:{{ no }}) {{ val.name }} {{ val.price }}円 {{ val.sale }}
 </li>
</ul>
<button @click="test5(980, $event)">click!</button>

引数を持たせてインラインで実行する事もできます。この場合 $event で元のイベントオブジェクトを渡せます。

var vm = new Vue({
 el: '#app',
 data: {
  test5list: [{
   'name': 'とまと',
   'price': '100'
  }, {
   'name': 'れたす',
   'price': '200'
  }, {
   'name': 'きゅうり',
   'price': '300'
  }]
 },
 methods: {
  test5: function(price) {
   this.test5list[0].price = price
   this.test5list[0].sale = 'おすすめ'
  }
 }
})

出来ました。配列の値を直接弄るわけでなければ大丈夫みたいです。中のオブジェクトのセッターが働いているのでしょうか。手元でセッター付きオブジェクトのネストの実験をしてみたのですがセッター&ゲッターについてもちょっと勉強できました。

データを更新する時のハマりポイント

オブジェクトにネストされていた場合でも、インデックス数値を使って配列を更新する場合は $set を使わないと反応してくれません!どうしてもな場合以外は最後みたいにオブジェクトのリストにしてしまうのが楽かもしれませんね。

まとめ

データと要素を連動させるのは jQuery で書くよりとても楽ですが、それでもコードが大きくなるにつれてデータの整合性を保つのが大変になってくるとよく聞きます。大人数で開発するような大きなものを作ったことがないので漠然としたイメージしか出来ませんが。そこで登場するのが Vuex らしいのですけど勉強するのはまだまだ先になりそうかな!

今回は v-on でのイベント登録の仕方とデータ更新の基本を覚えました(•ө•)ノ 次回は条件を付けて何か操作したいと思います。たぶん。