現役エンジニアが教える!実践JavaScript入門 〜イベント処理〜

公開日:2022-09-04
JavaScript
イベント処理

https://youtu.be/kQiaAiv9NCE

今回扱う内容:イベント処理

イベント処理の基礎を理解しよう。

イベントとは

Web開発で使われるイベントとはブラウザ上で生じた動作や出来事のことを指します。

具体例としては次のようなものが挙げられます。

  • ユーザーがある要素をマウスでクリックしたり、カーソルを合わせたりする
  • ユーザーがキーボードのキーを押す
  • ユーザーがブラウザの画面をリサイズしたり閉じたりする
  • Webページのロードが完了する
  • フォームを送信する
  • ビデオを再生・停止・終了する
  • エラーが発生する

https://developer.mozilla.org/ja/docs/Learn/JavaScript/Building_blocks/Eventshttps://developer.mozilla.org/ja/docs/Learn/JavaScript/Building_blocks/Events

イベント処理とは

イベントに対して、何らかの実行させたい処理を登録することをイベント処理と言います。
イベント処理により、例えばボタンを押した際やエラーが起きた際にダイアログやアラートを表示させるなど、何かしらのインタラクションを起こすことができます。

イベントに関する用語

イベントハンドラー

イベントハンドラーとは、イベントが発火した際に実行されるコード(関数)のことを指します。特にイベントの発火に対する応答処理を定義することを「イベントハンドラーを登録する」と言い、こちらの言い回しでよく使われます。

イベントリスナー

イベントリスナーはイベントハンドラーと似たような意味で使われる用語ですが、厳密には違う意味を持ちます。イベントハンドラーがボタンを押した際に何かを実行させるものである一方で、イベントリスナーは応答処理にイベントの発生を監視させることができます。

イベントの使用方法

イベントの使用方法は次の3パターンがあります。

  • イベントハンドラープロパティ
  • インラインイベントハンドラー
  • イベントリスナー

イベントハンドラープロパティ

基本のイベント処理の記述方法です。

次のサンプルコードでは、ボタンを押すたびにランダムな整数値の色に背景色を変更できます。
このイベントハンドラーの登録方法はまずquerySelectorメソッドでbutton要素の参照を取得します。次にボタンを押した際のイベントハンドラープロパティであるonclickプロパティに、bodyの背景色を変更するbgChange関数を代入します。

const random = (number) => Math.floor(Math.rondom() * (number + 1));
const bgChange = () => {
  const rndCol = 
  "rgb(" + random(255) + "," + random(255) + "," + random(255) + ")";
  document.body.style.backgroundColor = rndCol;
};
const btn = document.querySelector("button");
btn.onclick = bgChange; //イベント処理の登録

またonclickプロパティに無名関数を直接代入する書き方もあります。

const btn = document.querySelector("button");
btn.onclick = function () {
  const rndCol = 
  "rgb(" + random(255) + "," + random(255) + "," + random(255) + ")";
  document.body.style.backgroundColor = rndCol;
}

インラインイベントハンドラー

こちらは現在では推奨されていないイベント処理の記述方法です。

書き方としてはhtmlの中に直接書く記述方法で、次のようにbuttonタグを書き換えると先ほどと同様に背景色の変更ができます。ですがJavaScriptをHTMLに直接書いてしまうと、コードが複雑になるにつれ見づらくなってしまうという問題点があります。

sample.html
<button onclick="bgChange()">button</button>

一方で例えばJSフレームワークのReactを用いた開発では次のようにイベント処理を記述することがあり、インラインイベントハンドラーに似た書き方となります。念頭に置いといておきましょう。

sample.js
<button onClick={handleClick}>button</button>

イベントリスナー

先ほどと異なりonclickメソッドにbgChangeを渡すのではなく、addEventListenerメソッドを呼び出し登録します。イベントハンドラープロパティに似た書き方ですが、イベントリスナーでは応答処理を削除したり、同種のリスナーを複数登録できます。

const btn = document.querySelector("button");
btn.addEventListener ("click", bgChange);

イベントオブジェクトとは

イベント処理内でeと名付けられた引数がよく使用されます。これはイベントオブジェクトと呼ばれるもので、イベントの追加機能や情報を提供する目的でイベントハンドラー関数に自動で渡される引数のことです。複数の要素に同じイベントハンドラーを割り当て、どれかでイベントがあったら共通の何らかの処理を作用させたいときに有用です。

具体的にはイベントオブジェクトを使って前節で使っていたbgChangeを次のように書き換えます。このように書くことでイベントオブジェクトからイベントが発生した要素の情報を取得でき、どの要素の背景色を変更するかを決めることができます。

const div = document.querySelector("div");
const bgChangeE = (e) => {
  "rgb(" + random(255) + "," + random(255) + "," + random(255) + ")";
  e.target.style.backgroundColor = rndCol;  //e.target : イベントがあった要素を参照
};
div.addEventListener("click", bgChangeE);

またイベントオブジェクトを使うことでデフォルトの動作を抑制できます。
例えば名前と名字を送るフォームがあり、名前が入力されていない状態では送信が行わないようにしたいとします。 その場合、イベントオブジェクトのpreventDefaultメソッドを使うことでイベント処理の抑制ができます。

フォーム

const form = document.querySelector("form");
const fname = document.getElementById("fname");
const lname = document.getELementById("lname");
const para = document.querySelector("p");
form.onsubmit = function (e) {
  if (fname.value === "" || lname === ""){
    e.preventDefault(); //preventDefault : イベント処理(送信)を行わない
    para.textContent = "You need to fill in both names!";
  }
}

イベントの伝達

HTMLは入れ子構造になっているので、親の要素をもつ要素におけるイベントの実行順番について説明します。モダンブラウザーではイベントの伝達は2パターンあり、キャプチャリングバブリングと呼ばれます。

1つ目のキャプチャリングは図の左側を指すイベントの伝達であり、親要素から子要素に向けてイベントが伝達されます。
2つ目のバブリングは図の右側を指すイベント伝達であり、子要素から親要素に向けてイベントが伝達されます。
今のブラウザではバブリングでのイベント伝達が一般的です。

eventの伝達
イベントの伝達図

バブリングについてもう少し詳しく見ていきます。
次の図のような3つのエリアである、動画を表示させるbtn、動画を非表示にするvideoBox、動画を再生させるvideoに分けて、動画の再生や表示の実装をする場合ついて考えます。

作成したい動画の再生ページ
作成したい動画の再生ページ

次のように実装すると、動画を再生しようとvideoをクリックした際に親要素であるvideoBoxの動画を非表示にするイベントもバブリングで伝わってしまい動画再生と非表示の両方が実行されてしまいます。

const btn = document.querySelector('button');
const videoBox = document.querySelector('div');
const video = document.querySelector('video');
btn.onClick = () => {
  videoBox.removeAttribute('class', 'hidden'); //動画を非表示にするhiddenを削除
};
videoBox.onClick = () => {
  videoBox.setAttribute('class', 'hidden'); //動画を非表示にするhiddenを追加
};
video.onClick = () => {
  video.play();
};

これを防ぐためには子要素でstopPropagation()メソッドを使用することで、親要素のイベントの伝達を止めることができます。
今回の場合は、次のように書き換えることでvideoをクリックした場合も動画が非表示されることなく再生できます。

video.onClick = (e) => {
  e.stopPropagation(); //親要素のイベントの伝達を防ぐ
  video.play();
};

まとめ

今回はイベントについて解説しました。前回のDOM操作に引き続きJavaScriptで動的なサイトを作る際にはよく使われるので、ぜひマスターしましょう。
次回はDOM操作とイベント処理の実践編を解説します。