今回はVue.jsでのイベントハンドリングを紹介します。
Notice
記事中のCodePenは右上の "Edit on CodePen" からコード編集画面に遷移できます。
ぜひ手元でコードを変えて結果を確かめてみてください。理解が早まると思います。
前提
マシーン | ブラウザ | Vue |
---|---|---|
macOS Sierra 10.12 | Firefox Quantum | ver. 2.5 |
イベントとmethods
Vue.jsでのイベントハンドリングは普通にHTMLにJavaScriptを書くのとほとんど同じなので、わかりやすいかと思います。
イベントの登録には以下のように v-on
属性を用います。
<button v-on:click="something = true">Push</button>
v-on:イベント名="***"
という形式で記述します。属性の値の部分はJavaScriptの式もしくはメソッド名です。
v-on:
の部分は @
で置き換えることができます。v-on:click="***"
であれば、@click="***"
とも書けるわけです。@
は糖衣構文であって、2通りの書き方に機能的な違いは全くありません。私は @
の方が短く視認性にも優れると感じるので @
を使います。
@
属性の値にはメソッド名も取れると書きましたが、単なる関数ではいけません。以下のように、Vueインスタンスの生成時にコンストラクタに渡す設定オブジェクトの methods
プロパティに定義された関数でなくてはならないのです。
<button @click="someFunc">Push</button>
<script>
var app = new Vue({
el: '#app',
data: {
something: false
},
methods: {
someFunc: function () {
this.something = true
}
}
})
</script>
data
プロパティに定義された変数でなければVueアプリ内で扱えないのと同様ですね。(上記の例において、someFunc
関数内で data
プロパティに定義された something
に、this
を通してアクセスしていることにお気づきでしょうか。この点については後ほど説明します。)
設定オブジェクトのプロパティはVue.jsアプリケーションにおいて特別な意味を持ちます。el
と data
に続き methods
プロパティも覚えておきましょう。
methods
プロパティに定義された関数はイベントハンドラとしてしか使えない、というわけではありません。
<button @click="someFunc">Push</button>
<script>
var app = new Vue({
methods: {
someFunc: function () {
this.hello()
},
hello: function () {
console.log('hello')
}
}
})
</script>
このように、設定オブジェクト内では this
を通してアクセスすることができます。
設定オブジェクトでの this は何者か?
設定オブジェクトで this
を初めて登場させましたので、少し説明を加えます。
<button @click="someFunc">Push</button>
<script>
var app = new Vue({
el: '#app',
data: {
name: 'Evan You'
},
methods: {
someFunc: function () {
this.hello()
},
hello: function () {
console.log('Hello, ' + this.name)
}
}
})
</script>
ご覧の通り、data
に定義された変数や methods
に定義された関数には、設定オブジェクト内では this
を通してアクセスすることができます。
ここで this
が指し示すものは、Vueインスタンスです。
this
は設定オブジェクトそのものではありませんのでご注意ください。例えば this.methods
などと書いて methods
プロパティにアクセスすることはできません。
下の図は設定オブジェクト内で this
をコンソール出力した結果です。
赤枠で囲った部分にご注目ください。data
や methods
に定義した変数・関数が、Vueインスタンスのプロパティに加えられていますね。だからこそ、this
がVueインスタンスを指すときに、 this.hello()
のようなアクセスが可能となるわけです。
さて、最後にいくつかイベントの利用例を見ていきましょう。
タブ - @click
See the Pen Vue onClick by Masahiro Harada (@MasahiroHarada) on CodePen.
簡単なタブのサンプルです。
clickイベントで currentTab
の値を切り替えています。ここで注目していただきたいのは @click="toggle(1)"
のように、イベントハンドラは引数を取れるということです。
あとはタブのコンテンツ側(文章が書いてある側)で v-show
を用いて、currentTab
の値にしたがって要素を見せたり隠したりしています。つまり、toggle
関数内で currentTab
の値が変更されるとすぐに(自動的に)テンプレート側にもその変更が反映され、v-show
が再評価されています。このようなUIとデータのシームレスな連携はVue.jsの真価と言えるでしょう。
フォーム - @submit
See the Pen Vue onSubmit by Masahiro Harada (@MasahiroHarada) on CodePen.
続いてフォームの例です。
この例で注目していただきたいのは、@submit.prevent="onSubmit"
です。
Ajaxを用いてフォーム送信をする場合、Vue.jsを使わずに書くと以下のようにメインロジックの前に preventDefault
メソッドを実行するかと思います。
function onSubmit (event) {
event.preventDefault()
// メインロジックがつづく...
}
preventDefault
メソッドを実行しないと、Ajaxリクエストを送りたいメインコードなどお構いなしにHTML側でのフォーム送信が走って画面遷移が発生してしまうからですが、まぁこの辺はみなさんご存知かもしれません。
Vue.jsでは、@submit.prevent
と書くと勝手に preventDefault()
してくれます。
便利ですね。
ちなみに上で指摘したデフォルトのフォーム送信を避けるために、例えば <form>
を書かず <button>
の type
属性を "submit"
ではなく "button"
としてclickイベントでAjax通信を行っても動きとしては変わりませんが、そのような書き方はアクセシビリティ的にはNGらしいです。
どこがフォームでどこが送信ボタンなのかわからなくなってしまうからなのだそうです。
ファイルプレビュー - @change
See the Pen Vue File Preview by Masahiro Harada (@MasahiroHarada) on CodePen.
こちらはフォームで選択した画像ファイルをその場でプレビュー表示する例です。
前回のフォーム入力についての記事でも言及しましたが、<input type="file">
の場合は v-model
では選択したファイルそのものは取得できません。
そのため(Vue.jsを使わない場合と同様に)<input>
のchangeイベントでeventオブジェクトを受け取ってそこからファイルを取得します。
<input type="file" @change="onFileChange" accept="image/*">
methods: {
onFileChange: function (event) {
このように、イベント登録側では特に何も書かなくても、ハンドラの引数としてeventオブジェクトを受け取ることができます。
ただしeventオブジェクトの他にも引数を渡したい場合にはeventオブジェクトも明示的に指定してやる必要があります。
<button type="button" @change="onClick(event, 123)">Push</button>
methods: {
onClick: function (event, number) {
以上、Vue.jsでのイベントハンドリングを紹介しました。
より詳しくはマニュアルを参照してください。
イベントハンドリング — Vue.js
関連記事
Vue.js入門(全7回)
- Vue.js入門 (1) el, data
- Vue.js入門 (2) テンプレート
- Vue.js入門 (3) クラスとスタイル
- Vue.js入門 (4) フォーム入力
- Vue.js入門 (5) イベントとmethods
- Vue.js入門 (6) 算出プロパティ
- Vue.js入門 (7) ウォッチャ