イベント
イベントとはマウスクリックやドラッグ&ドロップなどユーザーの操作によって発生する動作や、Local Storageの操作のようなシステムで生じた出来事のことを指します。
JavaScriptを用いることでイベントが発火した時に特定のJavaScriptの関数を実行させられます。その関数のことをイベントハンドラと呼び、それをイベントに紐づけるように定義することをイベントハンドラを登録すると言います(イベントハンドラはJavaScriptの関数と書きましたが、厳密にはそれに限定せず実行される特定のコードブロックのことを指します)。
下の例ではbutton
というid
を持つ要素をクリックしたときにアラートを出すようなイベントハンドラを登録しています。
const button = document.getElementById('button');
button.addEventListener('click', () => {
alert('clicked')
});
addEventListener
でイベントハンドラの登録を行なっています。第1引数で登録するイベントを指定して、第2引数でイベントハンドラを記述します。
See the Pen EventHandler by KokiSakano (@kokisakano) on CodePen.
イベントハンドラではさらに、Event
インターフェイスを介してイベントのプロパティやメソッドを呼び出せます。
target
プロパティでイベントの発火元、type
プロパティでイベントの種類のように様々な情報を扱えます。例えば以下の例ではEvent
からtimeStamp
を取得してそれを表示させています。
See the Pen EventHandler by KokiSakano (@kokisakano) on CodePen.
次に下記のようなHTML構造を考えます。
- div
- div
- button
そして、すべての要素のクリックに対してイベントハンドラが登録されているとします。その時、button
をクリックするとbutton
のイベントハンドラが発火し、その親のdiv
に登録されたイベントハンドラ、さらにその親のdiv
に登録されたイベントハンドラが発火します。
See the Pen Event by KokiSakano (@kokisakano) on CodePen.
この現象はバブリングと呼ばれる仕組みによって生じます。
バブリングはイベントが生じた時に、その要素のイベントハンドラを実行し、次にその親要素のイベントハンドラを実行し、さらにその親のイベントハンドラを実行するようにイベントハンドラを対象の要素から親要素へと辿って実行することを指します。
先ほどの例ではdiv→div→button
という構造でしたので、button
のイベントハンドラが発火、内側のdiv
のイベントハンドラが発火、外側のdiv
のイベントハンドラが発火の順で処理されました。
stopPropagation
例えばリンクによるページ遷移を行う場合にその親のクリックイベントを発火させないようにバブリングを止めたいことがあります。その時は、対象のイベントハンドラでEvent
を受け取ってstopPropagation
を呼び出すことでバブリングを阻止できます。
const button = document.getElementById('button');
button.addEventListener('click', (e) => {
e.stopPropagation();
alert('clicked')
});
See the Pen stopPropagation by KokiSakano (@kokisakano) on CodePen.
stopImmediatePropagation
Event
が持つ似たようなメソッドとしてstopImmediatePropagation
があります。
stopImmediatePropagation
もバブリングに関するメソッドで、stopPropagation
は親要素のイベントハンドラの実行を防ぐだけだったのに対して、このメソッドはそれ以降に登録された同要素に対してのイベントハンドラの発火も防ぎます。
const button = document.getElementById('button');
// 発火する
button.addEventListener("click", () => {
alert(1);
});
// 発火する
button.addEventListener("click", (e) => {
e.stopImmediatePropagation();
alert(2);
});
// 発火しない
button.addEventListener("click", () => {
alert(3);
});
以下の例ではbutton
に対してそれぞれ2つのイベントハンドラを登録し、1つ目のイベントハンドラでそれぞれstopPropagation
、stopImmediatePropagation
を呼び出すことで動作差分を確認できます。
See the Pen stopImmidiatePropagation by KokiSakano (@kokisakano) on CodePen.
preventDefault
ブラウザにはそれぞれのイベントに対するデフォルトの挙動が実装されています。例えばチェックボックスにはクリックすると見た目が切り替わる挙動が実装されています。
チェックボックスのクリックに対してe.preventDefault
を呼び出すイベントハンドラを登録するとその挙動が呼び出されません。
const input = document.getElementById("remove");
input.addEventListener('click', (e) => {
e.preventDefault();
});
See the Pen EventHandler by KokiSakano (@kokisakano) on CodePen.