JavaScriptで「イベント」に処理を追加するaddEventListener()メソッドのオプション値とイベント伝搬について理解しよう

addEventListener()のオプションについて理解する

既に、addEventListener()メソッドについては紹介していますが、このメソッドにはオプション値があります。

オプション意味
captureキャプチャーフェーズを取得するかどうか真偽値
onceリスナーの呼び出しを1回だけにするか真偽値
passiveパッシブイベントかどうか真偽値
addEventListener()のオプション値

しかし、このオプション値の役割のうち、captureについては、事前に「イベント伝搬」について理解しておく必要があります。

JavaScriptの「イベント伝搬」とは?

イベント伝搬とは、イベントバブリングとイベントキャプチャリングの両方をカバーする用語です。

そもそも、イベント名によっては、その要素に対してイベントが生成されるだけではなく、他の要素の同種のイベントを生成します。(clickmouseovermouseoutなど)

例えば、下記の様なコードを書いたとします。

HTML
<button class="mb-4" id="button">Button</button>

このボタンをクリックすると、まず対応するボタン要素のclickイベントが生成されます。ここまでは、周知の事実かと思います。しかし、それだけでは終わらず、このイベントはボタン要素だけではなく、その親や祖父に当たる要素のclickイベントまで生成されます。

DOM用語では、<button>イベントターゲットであり、この<button>要素をクリックしたということは、DOMの一番内側の要素でクリックが発生したことになります。

イベントターゲットを親からたどってwindowオブジェクトまでが、DOMツリーのブランチの構成です。<button>のブランチの構成は<button><body><html>documentwindowで構成されます。

quote-left

windowは、DOMノードではありませんが、EventTargetインターフェイスのインプリメントを簡単にするために、documentオブジェクトの親ノードのように扱います。

要するに「イベント伝搬」とは、「イベントターゲット(この場合<button>)からwindowオブジェクトに到る全てのブランチ構成要素に対して、発生したイベント(この場合はclick)のイベントリスナーに登録されている関数を実行していくプロセス」のことを指します。

それぞれのオプションを理解する

それぞれのオプション解説していきます。

capture

captureは「イベント伝搬」の方向を決めます。

Copyright © 2016 World Wide Web Consortium, (MIT, ERCIM, Keio, Beihang)

イベント伝搬の流れは・・・

  1. windowオブジェクトからイベントターゲットに向かい、その過程のイベントリスナーを呼び出していく「Capture Phase」
  2. イベントイベントターゲットのイベントを実行する「Target Phase」
  3. イベントターゲットからwindowオブジェクトへ向い、その過程のイベントリスナーを呼び出していく「Bubbling Phase」

の3つになります。

通常、addEventListener()captureオプションはfalseです。これは「イベント伝搬」が起こり、イベントターゲットのブランチ要素に付与されている関数は「Bubbling Phase」で実行されるということです。

つまり・・・処理の実行手順は

  1. イベントターゲットに追加された処理を実行
  2. 各ブランチに追加された処理をDOMの内側から実行

となります。

これを、イベントターゲット.addEventListener(イベント名,リスナー,option ={capture:true})とした場合どうでしょうか?

Capturetrueになったので、処理の実行手順は

  1. 各ブランチに追加された処理をDOMの外側から実行
  2. イベントターゲットに追加された処理を実行

となります。

この様に処理の順番を指定するオプションがcaptureです。

once

ページを読み込んだあと、イベントリスナーとして登録した処理を実行したい場合はonceオプションをtrueに設定します。

Passive

このオプションはイベントリスナーとして登録された処理を「非同期処理」にするかを指定します。

通常、イベントリスナーに登録された関数は1つずつ順番に処理されますが、パフォーマンス向上の観点から、他の処理を待たなくても支障が出ない処理についてはPassiveオプションをtrueにするケースがあります。

サンプルコード

サンプルコードとして、アラートダイアログボックスに対して、明示的にオプションを指定したものを紹介します。

Output

一度だけ実行されるアラート

Pug
p 一度だけ実行されるアラート
 button#button.mb-4 Button
SCSS
#button {
	--background-color: #fff;
  --color: #576574;
	--transition: all .3s;
	margin-bottom: 10px;
  background-color: var(--background-color);
  padding: 10px;
  color: var(--color);
	border: 1px solid #576574;
  cursor: pointer;
  width: 120px;
	transition:  var(--transition);
	&:hover {
		transition: var(--transition);
		color: var(--background-color);
		background-color: var(--color);
	}
}
JavaScript
// ボタンをクリックしたら予め用意していたonClickAction()関数を実行する
onClickOption = {
	capture: true,
	once: true,
	passive: true
};
document.getElementById('button').addEventListener('click', onClickAction, onClickOption);

/** ボタンをクリックするとアラートを表示 */
function onClickAction() {
	//アラートを表示
	const dateInstance = new Date();
	window.alert(`こんにちは!今日の日付は${dateInstance.getFullYear()}年${dateInstance.getMonth() + 1}月${dateInstance.getDate()}日です。`);
}

見かけではわかりづらいと思いますが、このアラートボタンが1度しか機能しないのは確認できます。

インストラクター
コメント

コメントを残す