カテゴリ: notes
タグ: vuejs

イベントハンドリング|Vue.js再学習

触れないタイミングが3ヶ月あったり忘れてしまった事に焦りを感じたので、今度は勉強したことをブロクに残していきたいと思います。 内容的には公式ドキュメントの写経のようなものになります。

今日はイベントハンドリングを見ていきます。

イベントハンドリング

イベントハンドリング

イベントの購読

v-onディレクティブを使うことで、DOMイベントの購読、イベント発火時のJavaScriptの実行が可能になります。

例:

<div id="example-1">
  <button @click="counter +=1">Add 1</button>
  <p>The button above has been clicked {{ counter }} times.</p>
</div>
var example1 = new Vue({
  el: '#example-1',
  data: {
    counter: 0
  }
})

メソッドイベントハンドラ

多くのイベントハンドラのロジックはより複雑になっていくので、v-on属性の値にJavaScript式を記述し続けるのは現実的ではありません。 そのため、v-onは呼び出したいメソッドの名前も受け付けます。

例:

<div id="example-2">
  <!-- `greet` は、あらかじめ定義したメソッドの名前 -->
  <button @click="greet">Greet</button>
</div>
var example2 = new Vue({
  el: '#example-2',
  data: {
    name: 'Vue.js'
  },
  // `methods` オブジェクトの下にメソッドを定義する
  methods: {
    greet: function (event) {
      // メソッド内の`this`は、Vueインスタンスを参照します
      alert('Hello ' + this.name + '!')
      // `event`は、ネイティブDOMイベントです
      if (event) {
        alert(event.target.tagName)
      }
    }
  }
})

// JavaScript からメソッドを呼び出すこともできます
example2.greet() // => 'Hello Vue.js!'

インラインメソッドハンドラ

メソッド名を直接指定する代わりに、インラインJavaScript式でメソッドを指定することもできます。

<div id="example-3">
  <button @click="say('hi')">Say hi</button>
  <button @click="say('what')">Say what</button>
</div>
new Vue({
  el: '#example-3',
  methods: {
    say: function (message) {{
      alert(message)
    }}
  }
})

時には、インラインステートハンドラでオリジナルのDOMイベントを参照したいこともあるでしょう。 特別な$event変数を使うことでメソッドにDOMイベントをwタスことができます。

<button @click="warn('Form cannot be submitted yet.', $event)">
  Submit
</button>
// ...
methods: {
  warn: function (message, event) {
    // ネイティブイベントを参照しています
    if (event) event.preventDefault()
    alert(message)
  }
}

イベント修飾子

イベントハンドラ内でのevent.preventDefault()またはevent.stopPropagation()の呼び出しは、様々な場面で共通に必要になります。 これらはメソッド内部で簡単に呼び出すことができますが、DOMイベントの込み入った処理を行うよりも、純粋なデータロジックだけになっている方がより良いでしょう。

この問題に対応するために、Vueはv-onのためにイベント修飾子(event modifires)を提供しています。 修飾子は、ドット(.)で表記されるディレクティブの接尾時を思い返してください。

  • .stop
  • .prevent
  • .capture
  • .self
  • .once
<!-- クリックイベントの伝搬が止まります -->
<a @click.stop="doThis"></a>

<!-- submit イベントによってページがリロードされません -->
<form @submit.prevent="onSubmit"></form>

<!-- 修飾子はつなげることができます -->
<a @click.stop.prevent="doThat"></a>

<!-- 値を指定せず、修飾子だけ利用することもできます -->
<form @submit.prevent></form>

<!-- イベントリスナーを追加するときにキャプチャモードで使います -->
<!-- 言い換えれば、内部要素を対象とするイベントは、その要素によって処理される前にここで処理されます -->
<div @click.capture="doThis">...</div>

<!-- event.target が要素自身のときだけ、ハンドラが呼び出されます -->
<!-- 言い換えると子要素のときは呼び出されません -->
<div @click.self="doThat">...</div>

修飾子を使用するとき、関連するコードが同じ順序で生成されるため注意してください。 それゆえ、v-on:click.prevent.selfを使用すると全てのクリックイベントを防ぐことはできますが、 v-on:click.self.preventは要素自身におけるクリックイベントを防ぐだけです。

2.1.4から新規

<!-- 最大1回、クリックイベントはトリガされます -->
<a @click.once="doThis"></a>

他の修飾子とは異なり、ネイティブDOMイベントには排他的ですが、.once修飾子はコンポーネントイベントでも使用することができます。

2.3.0から新規

VueはaddEventListenerpassiveオプションに対応する.passive修飾子も提供しています。

<!-- スクロールイベントのデフォルトの挙動(スクロール)は -->
<!-- `onScroll` が`event.preventDefault()`を含んでいる場合、 -->
<!-- イベントの完了を待たずに属座に起きるでしょう。 -->
<div @scroll.passive="onScroll">...</div>

.passive修飾子は特にモバイルでのパフォーマ酢を改善するのに有用です。

.passive.preventを一緒に使わないでください。.preventは無視され、ブラウザにはおそらく警告が表示されます。 .passiveはイベントのデフォルトの挙動を妨げないことをブラウザに伝達することを思いだしてください。

キー修飾子

キーボードイベントを購読するにあたって、時にはキーコードのチェックが共通で必要になります。 Vueは、v-onに対してキー修飾子を追加することで、キーコードのチェックを可能にします。

<!-- `keyCode` が13のときだけ、`vm.submit()`が呼ばれます-->
<input v-on:keyup.13="submit>

全てのキーコードを覚えることは大変なので、Vueは最も一般的に使用されるキーのエイリアスを提供します。

<!-- 上記と同じです -->
<input v-on:keyup.enter="submit">

<!-- 省略記法も同様に動作します -->
<input @keyup.enter="submit">

キー修飾子のエイリアスの全てのリストを示します。

  • .enter
  • .tab
  • .delete (“Delete”と”Backspace”キー両方をキャプチャします)
  • .esc
  • .space
  • .up
  • .down
  • .left
  • .right

グローバルなconfig.keyCodesオブジェクト経由でカスタムキー修飾子のエイリアスも定義できます

// `v-on:keyup.f1` を可能にします
Vue.config.keyCodes.f1 = 112

自動キー修飾子

2.5.0で新規追加

keyboardEvent.keyで公表されている任意の有効なキー名をケバブケースに変換することによって、修飾子として直接使用できます。

<input @keyup.page-down="onPageDown">

上記例では、ハンドラは$event.key === 'PageDown'の場合だけ呼ばれます。

いくつかのキー(.esc、そして全ての矢印キー)はIE9で一貫性のないkey値を持っています。 IE9をサポートする必要がある場合、組み込みのエイリアスが有線されます。

システム修飾子キー

2.1.0から新規

次の修飾子を使用すると、対応するキーが押されたときにのみマウスイベントリスナをトリガできます

  • .ctrl
  • .alt
  • .shift
  • .meta

metaはMacで⌘、Windowsで⊞、Sun Microsystemsでは◆になります。 MITやLispマシンのキーボード、Knightキーボード、space-cadetキーボード、メタのような後継機にはMETAと表示されます。 Symbolicsのキーボードでは、METAまたはMetaとラベルが付いています。

<!-- Alt + C -->
<input @keyup.alt.67="clear">

<!-- Ctrl + Click -->
<input @click.ctrl="doSomething">Do something</div>

修飾子キーは通常のキーとは異なり、keyupイベントと一緒に使用するときは、イベントが発生したときに押さなければならないことに注意してください。 言い換えると、keyup.ctrlctrlを押しながらキーを離した時にのみ、トリガされます。 ctrlキーだけを離すと、トリガされません。 そのような動作を望む場合、ctrlではなくkeyup.17のようにkeyCodeを使用してください。

.exact修飾子

2.5.0で新規追加

.exact修飾子はイベントを引き起こすために必要なシステム修飾子の正確な組み合わせを制御します。

<!-- これは MetaキーだけでなくAltキーを同時に押した場合でも、発行されます -->
<button @click.meta="onClick">A</button>

<!-- これはCrrlキーが押され、他のキーが押されてないときだけ発行されます -->
<button @click.ctrl.exact="onCtrlClick">A</button>

マウスボタンの修飾子

2.2.0で新規追加

  • .left
  • .right
  • .middle

これらの修飾子は、イベントのトリガのハンドリングを、特定のマウスボタンのみに制限します。

なぜ HTML にリスナを記述するのですか

これまで説明してきたようなイベント監視のアプローチは、”関心の分離”という古き良きルールを破っているのではないか、と心配されるかもしれません。 安心してください。すべてのVueハンドラ関数と式は、現在のViewを扱うViewModelに厳密に閉じています。 それによってメンテナンスが難しくなることはありません。 実際、v-onを利用することでいくつかの利点があります。

  • HTMLテンプレートを眺めることで、JSコード内のハンドラ関数を探すことを容易にします
  • JS内のイベントリスナーを手作業でアタッチする必要がないので、ViewModelをDOM依存のない純粋なロジックにできます。これはテスタビリティも向上します。
  • ViewModelが消去されるときに、すべてのイベントリスナーは自動で削除sれます。手動でそれらの消去をおこなうことを気にする必要はありません。

About

はらぺこ

職業:フロントエンドエンジニア
趣味:自転車/テニス/空手
愛車:
 ✓ブリヂストン オルディナs5
 ✓アンカー RS8 EL

神戸にて爆誕。
友人から「お前がマスターして教えてくれ」と渡された『HTML&スタイルシート ポケットリファレンス』がキッカケでWeb業界への一歩を踏み出す事になる。

2013年7月にクロスバイクを購入して自転車にドハマリする。
全力で遊ぶ合間に、ほどほどに頑張る日々を過ごしています。

飼い主 はっぴー

2014年10月20日(誕生日)の引っ越し日、捨て猫になっていた所、運命の出会いを果たす。 
(その日は雨で、3日間雨が続く寒い日だった。このまま放っておけないと自転車生活と秤にかけて、はっぴーを選択する)
5時間かけて油断させ、近づいてきた所をガッと拾い上げ、そのまま家へ猛ダッシュ、玄関の鍵を閉めて家族になる。以後オレたちはファミリーだ。

助けたつもりが、実際は自分の方が精神的に救われている。はっぴーなしでは生きていけない。(最早「飼い主」と言って差し支えないだろう)

「はっぴー」という名前の由来は、『幸せになってほしい』という想いで名付けた。