Vue.js　イベントハンドリング

#Vue.js イベントハンドリング

前回の記事はこちら
[Vue.js　条件付きレンダリング](https://qiita.com/fumiya0414/items/250d6547047b16639c5f)

##インラインイベントハンドラ
[jsfiddle](https://jsfiddle.net/)で実際に記述しながら読むことをおすすめします。

v-onディレクティブを使うとDOMイベントの購読、イベント発火時のjavascriptの実行が可能です。
クリックボタンを押す回数をカウンターにしてみましょう

```html:index/html
<div id="app">
  
<p>
  {{ counter }}
</p>

<button v-on:click="counter ++">
  click
</button>
  
</div>

<script src ="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
```

```javascript:index.js
var app = new Vue({
  el:'#app',
  data:{
    counter: 0
  }
})
```

実行結果
[![Image from Gyazo](https://i.gyazo.com/a4900e994a04abca4fbf261ced42468a.gif)](https://gyazo.com/a4900e994a04abca4fbf261ced42468a)

v-onディレクティブで補足されたcounterに属性として記述された処理（++）が実行されています。

##メソッドイベントハンドラ
上記では属性の値に処理を記述しましたが複雑な処理を記述するには限界があります。
メソッドイベントハンドラを使ってメソッド名として記述してみましょう

以下のように書き直します

```html:index/html
<div id="app">
  
<p>
  {{ counter }}
</p>

<button v-on:click="clickHandler">
  click
</button>
  
</div>

<script src ="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
```

```javascript:index.js
var app = new Vue({
	el:'#app',
  data:{
    counter: 0
  },
  methods:{
    clickHandler:function(){
      this.counter++
    }
  }
})
```
実行結果
[![Image from Gyazo](https://i.gyazo.com/ca00d08433686f1436daf5beedd776b0.gif)](https://gyazo.com/ca00d08433686f1436daf5beedd776b0)

動作は同じですがメソッドオプションを使うため
処理が複雑になってもhtmlの見通しが悪くなることはありません。

##イベントオブジェクトの参照
イベントハンドラのメソッドに引数を指定しイベントオブジェクトを取得することができます。

上記のカウンターからイベントオブジェクトを参照し
コンソールに表示してみましょう。

```html:index/html
<div id="app">
  
<p>
  {{ counter }}
</p>

<button v-on:click="clickHandler">
  click
</button>
  
</div>

<script src ="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
```

```javascript:index.js
var app = new Vue({
	el:'#app',
  data:{
    counter: 0
  },
  methods:{
    clickHandler:function(event){
      this.counter++
      console.log(event) //イベントの取得
      console.log(event.target.tagName) //タグの取得
      console.log(event.target.innerHTML) //htmlの取得
      console.log(event.target.type) //タイプの取得
    }
  }
})

```
実行結果
[![Image from Gyazo](https://i.gyazo.com/bc6d054417317f27da2564051380e4e0.gif)](https://gyazo.com/bc6d054417317f27da2564051380e4e0)
イベント、タグ、html、タイプをコンソールに表示ができています。

##イベントハンドラに引数を渡す
clickHandlerメソッドの引数に文字列を渡して
クリックで表示してみましょう

```html:index/html
<div id="app">
  
<p>
  {{ message }}
</p>

<button v-on:click="clickHandler('Vue.js')">
  click
</button>

<pre> <!--デバッグ用-->
  {{$data}}
</pre>
  
</div>

<script src ="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
```

```javascript:index.js
var app = new Vue({
	el:'#app',
  data:{
    message:''
  },
  methods:{
    clickHandler:function(message){
      this.message = message
    }
  }
})
```
実行結果
[![Image from Gyazo](https://i.gyazo.com/279722b32d913d994f56b71d4d699b8b.gif)](https://gyazo.com/279722b32d913d994f56b71d4d699b8b)

クリックによってclickHandlerメソッドで引数として渡された
Vue.jsの文字列がdataオプションに格納されて
messageとして表示されました。

##$event
上記では引数で"Vue.js"の文字列を使用しているのでeventの取得ができません。
このようなときは$eventを引数に明示することでeventが取得できます。

以下を記述してみましょう

```html:index/html
<div id="app">
  
<p>
  {{ message }}
</p>

<button v-on:click="clickHandler($event, 'Vue.js')">
  click
</button>

<pre>
  {{$data}}
</pre>
  
</div>

<script src ="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
```

```javascript:index.js
var app = new Vue({
  el:'#app',
  data:{
    message:''
  },
  methods:{
    clickHandler:function($event,message){
      this.message = message
      console.log($event)
    }
  }
})
```
実行結果
[![Image from Gyazo](https://i.gyazo.com/084fb4c42d3a9dce64728661c19f890e.gif)](https://gyazo.com/084fb4c42d3a9dce64728661c19f890e)

引数として文字列とeventを渡すことができています。

##イベント修飾子
v-onのためにクリックなどのDOMイベントの振る舞いを変更する修飾子が用意されています

代表的な修飾子は以下のとおりです。
.stop　イベントの親要素への伝搬を中止
.prevent　イベント規定の操作をキャンセル
.capture　イベントハンドラをキャプチャモードで動作
.self　イベント発生元が要素実親の場合だけ実行
.once　イベントハンドラを１回だけ実行
.passive　passiveモードを有効化

.onceを例にして記述してみましょう。
ボタンをクリックしたら現在時刻を取得するが２回目以降は動作しないプログラムを記述します。

```html:index/html
<div id="app">

<p>
  {{ message }}
</p>

<button v-on:click.once="clickHandler">
  click
</button>
  

</div>

<script src ="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
```

```javascript:index.js
var app = new Vue({
  el:'#app',
  data:{
    message:""
  },
  methods:{
    clickHandler:function(){
      this.message = new Date().toLocaleTimeString()
    }
  }
})
```

実行結果
[![Image from Gyazo](https://i.gyazo.com/d63d1b1452ec09e1300bc2a4f5807634.gif)](https://gyazo.com/d63d1b1452ec09e1300bc2a4f5807634)

１回目のクリックで現在時刻を取得しますが２回目以降は動作しません。
.once修飾子を外すと押した時刻を何度でも取得できます。

##キー修飾子
キーイベントをフックにして特定のキーコードのキーが押された時のみ
特定のイベントハンドラを呼び出すことができます。

escキーが押されたらテキストの入力がクリアされるように記述してみましょう

```html:index/html
<div id="app">

  <input type="text" v-on:keyup.27="clear" v-model="message">
  <p>
    {{message}}
  </p>

</div>

<script src ="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
```

```javascript:index.js
var app = new Vue({
  el:'#app',
  data:{
    message:""
  },
  methods:{
    clear:function(){
      this.message = ""
    }
  }
})
```
[![Image from Gyazo](https://i.gyazo.com/2c3ea7eeb723855ce34602479187ba1c.gif)](https://gyazo.com/2c3ea7eeb723855ce34602479187ba1c)

入力後にescキーを押すことでinputをクリアできています。
[キーコード一覧](http://musou.s38.xrea.com/mQuery/keycode.html)

エスケープキーを以下のように記述することも可能です。

```html:index/html
  <input type="text" v-on:keyup.esc="clear" v-model="message">
```

また複数設定する場合はドットでつなぎましょう
下記はエスケープキー、スペースキー、↑キーを設定したサンプルです

```html:index/html
  <input type="text" v-on:keyup.esc.space.up="clear" v-model="message">
```

##システム修飾子
下記のシステム修飾子は対応するキーが押されている時に
処理を行うことができます。

.ctrl　ctrlキーが押されているとき
.alt　altキーが押されているとき
.shift　shiftキーが押されているとき
.meta　mac:コマンドキーが押されているとき　windows:windowsキーが押されているとき

ctrl + c で入力がクリアされるコードを記述してみましょう

```html:index/html
<div id="app">

<input type="text" v-on:keyup.ctrl.67="clear" v-model="message">

<p>
  {{message}}
</p>

</div>

<script src ="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
```

```javascript:index.js
var app = new Vue({
  el:'#app',
  data:{
    message:""
  },
  methods:{
    clear:function(){
      this.message = ""
    }
  }
})
```

実行結果

[![Image from Gyazo](https://i.gyazo.com/16ce29742b319fce89f5aae01238f005.gif)](https://gyazo.com/16ce29742b319fce89f5aae01238f005)

cキーのみ押した場合はcを、ctrl+cキーの場合は入力がクリアされます。

次にdiv要素の文字列をshiftキーを押しながらクリックで
clickHanderメソッドを呼び出しaleartダイアログを表示しましょう

```html:index/html
<div id="app">

<div v-on:click.shift="clickHandler">
  Click me
</div>

</div>

<script src ="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
```

```javascript:index.js
var app = new Vue({
  el:'#app',
  data:{
    message:""
  },
  methods:{
    clickHandler:function(){
      alert('shift + click')
    }
  }
})
```

実行結果
[![Image from Gyazo](https://i.gyazo.com/81dfd4e38e3c11087667901a0e637a3c.gif)](https://gyazo.com/81dfd4e38e3c11087667901a0e637a3c)

v-on:cliskディレクティブにシステム修飾子を付加してshift+clickで
clickHandlerメソッドを呼び出しています。

次回はフォーム入力バインディングについてです。
[Vue.js　フォーム入力バインディング](https://qiita.com/fumiya0414/items/a5e1ef929095d6f011fc)