現役エンジニアが教える!実践JavaScript入門 〜イベント処理〜
今回扱う内容:イベント処理
イベント処理の基礎を理解しよう。
イベントとは
Web開発で使われるイベントとはブラウザ上で生じた動作や出来事のことを指します。
具体例としては次のようなものが挙げられます。
- ユーザーがある要素をマウスでクリックしたり、カーソルを合わせたりする
- ユーザーがキーボードのキーを押す
- ユーザーがブラウザの画面をリサイズしたり閉じたりする
- Webページのロードが完了する
- フォームを送信する
- ビデオを再生・停止・終了する
- エラーが発生する
https://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に直接書いてしまうと、コードが複雑になるにつれ見づらくなってしまうという問題点があります。
<button onclick="bgChange()">button</button>
一方で例えばJSフレームワークのReactを用いた開発では次のようにイベント処理を記述することがあり、インラインイベントハンドラーに似た書き方となります。念頭に置いといておきましょう。
<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つ目のバブリングは図の右側を指すイベント伝達であり、子要素から親要素に向けてイベントが伝達されます。
今のブラウザではバブリングでのイベント伝達が一般的です。
イベントの伝達図
バブリングについてもう少し詳しく見ていきます。
次の図のような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操作とイベント処理の実践編を解説します。