目次
イベントとは何か
イベント定義
「ブラウザ内で起こった何か(ユーザー操作・読み込み完了など)」をJavaScript が通知として受け取るための仕組み
代表例:
- ユーザー操作
click,dblclick,mousedown,mouseupkeydown,keyup,input,changesubmit(フォーム送信)
- ドキュメントやリソースの状態変化
load,DOMContentLoaded,error
- スクロールやサイズ変更
scroll,resize
- その他
hashchange,popstate(URL変化)focus,blurなど
JS から見ると、「イベントが起きたときに呼ばれる関数(イベントリスナ)」を登録しておき、
ブラウザが適切なタイミングで実行してくれる、という形になります。
イベントリスナの基本:addEventListener
基本形
構文:
target.addEventListener(type, listener, options?);target:イベントを受け取る対象(Element,window,documentなど)type:イベント名("click","input"など)listener:イベント発生時に呼ばれる関数((event) => { ... })options(省略可):オプション(capture,once,passiveなど)
例:
const button = document.querySelector("#myButton");
button.addEventListener("click", () => {
console.log("ボタンがクリックされました");
});重要ポイント:
- HTMLに
onclick="..."と書く「インラインイベント」は、基本的に避ける(保守性・セキュリティ的に弱い) - JS側で
addEventListenerを使うのが現代的な標準
リスナの削除:removeEventListener
function handleClick() {
console.log("クリック!");
}
button.addEventListener("click", handleClick);
// 後で解除
button.removeEventListener("click", handleClick);- 同じ関数オブジェクトを渡さないと解除できません
- 無名関数(
() => {})を直接渡すと、あとから解除しにくい
once オプション(一度だけ実行)
button.addEventListener(
"click",
() => {
console.log("最初の1回だけ反応");
},
{ once: true }
);{ once: true }を指定すると、1回実行されたあと自動で remove される- 「1回だけの確認ダイアログ」や「初期化処理」などに便利
イベントオブジェクトと this / target / currentTarget
イベントオブジェクト event
リスナには、ブラウザから イベントの情報を持ったオブジェクト が渡されます。
button.addEventListener("click", (event) => {
console.log(event.type); // "click"
console.log(event.target); // 実際にクリックされた要素
});click イベントの場合に代表的なプロパティ:
event.type:イベントの種類(”click” など)event.target:イベントの発生元(実際にクリックされた要素)event.currentTarget:このリスナが紐付いている要素- マウス系:
clientX,clientY,buttonなど - キー系:
key,code,altKey,ctrlKey,shiftKeyなど
target と currentTarget の違い
<ul id="list">
<li>アイテム1</li>
<li>アイテム2</li>
</ul>const list = document.querySelector("#list");
list.addEventListener("click", (event) => {
console.log("target:", event.target); // 実際にクリックされた<li>など
console.log("currentTarget:", event.currentTarget); // このリスナが付いている<ul>
});target:イベントを最初に発生させた要素currentTarget:どの要素のリスナがいま実行中か
後述するイベント伝播を理解すると、この違いがよりクリアになります。
this の意味(function vs アロー関数)
通常の function で書いたとき:
button.addEventListener("click", function (event) {
console.log(this === event.currentTarget); // true
});- 非strictな古めの挙動もありますが、イベントハンドラ内の
thisは
基本的にはevent.currentTargetを指す、と覚えておいてOKです。
アロー関数の場合:
button.addEventListener("click", (event) => {
console.log(this); // 外側のthisをキャプチャする(通常undefined)
});- アロー関数は
thisを自前で持たない(レキシカルthis) - イベントハンドラで
thisを使いたいなら、function構文の方が分かりやすいことがありますが、
普段はevent.currentTargetを参照すれば十分です。
イベント伝播:キャプチャリングとバブリング
3段階の伝播
DOMイベントは、1回のイベントで次のような流れで伝わります:
- キャプチャフェーズ
window→document→ … → 親要素 → … → 目的の要素まで下りてくる - ターゲットフェーズ
目的の要素そのもの - バブリングフェーズ
目的の要素から、親 → さらに親 → … →document→windowと上に上がっていく
多くの場合、開発で意識するのは バブリング です。
デフォルトは「バブリングフェーズで発火」
parent.addEventListener("click", handler);
child.addEventListener("click", handler);通常は、子要素がクリックされると:
- まず子要素の
clickリスナ - それから親要素の
clickリスナ - さらに上の親… という順に呼ばれる(バブリング)
capture オプションでキャプチャフェーズを使う
parent.addEventListener(
"click",
(event) => {
console.log("キャプチャ phase");
},
{ capture: true }
);{ capture: true }を指定すると、キャプチャフェーズで実行されるaddEventListener(type, listener, true)と書く古い書き方もあります
たとえば:
parent.addEventListener(
"click",
() => console.log("parent capture"),
{ capture: true }
);
child.addEventListener("click", () => console.log("child bubble"));
parent.addEventListener("click", () => console.log("parent bubble"));子をクリックしたときの順序:
parent capture
child bubble
parent bubble event.stopPropagation() / stopImmediatePropagation()
event.stopPropagation():
→ これ以上、上位(または下位)の要素へイベントを伝播させない
child.addEventListener("click", (event) => {
event.stopPropagation();
console.log("child only");
});
parent.addEventListener("click", () => {
console.log("parent"); // 呼ばれない
});event.stopImmediatePropagation():
→ 同じ要素に複数リスナがある場合でも、残りのリスナも実行させない
なるべく濫用は避けて、「本当にここで止めないとまずい」ケースに限定するのがよいです。
デフォルトアクションと preventDefault
多くのイベントには「ブラウザ側の標準動作(デフォルトアクション)」があります。
<a href="...">のクリック → ページ遷移<form>の submit → フォーム送信(ページリロード)input type="checkbox"のクリック → チェックON/OFF
これをキャンセルしたいときに使うのが event.preventDefault()。
フォーム送信をJSで制御する例
<form id="loginForm">
<input name="user" />
<button type="submit">送信</button>
</form>const form = document.querySelector("#loginForm");
form.addEventListener("submit", (event) => {
event.preventDefault(); // 標準の送信(ページリロード)を止める
console.log("ここでAJAX送信などを行う");
});リンクのクリックを無効化する例
const link = document.querySelector("#dangerLink");
link.addEventListener("click", (event) => {
event.preventDefault();
console.log("本当は遷移させたくない");
});代表的なイベント種別
よく使うイベントだけ、特徴をざっくり整理しておきます。
マウス・ポインタ
click:クリック完了時(基本これを使えば良い場面が多い)dblclick:ダブルクリックmousedown/mouseup:ボタン押下・解放mousemove:マウス移動(高頻度なので処理は軽く)mouseenter/mouseleave:要素の境界をまたいだ時(バブリングしない)mouseover/mouseout:子要素にも反応(バブリングする)
キーボード
input.addEventListener("keydown", (event) => {
console.log(event.key); // "a", "Enter", "Escape" など
console.log(event.code); // "KeyA", "Enter" など物理キーに対応
});keydown:キーが押された瞬間keyup:キーが離された瞬間keypress:古いイベント(今はkeydown/keyup前提でOK)
フォーム・入力系
input:入力値が変わったタイミング(ほぼリアルタイム)change:入力が確定したタイミング(blur や Enterなど)submit:フォーム送信ボタン or Enter で送信される直前
const input = document.querySelector("#name");
input.addEventListener("input", (e) => {
console.log("入力中:", e.target.value);
});
input.addEventListener("change", (e) => {
console.log("確定:", e.target.value);
});ドキュメント読み込み系
DOMContentLoaded:HTMLがパースし終わり、DOM構造が使えるようになったときload:画像なども含めた全てのリソース読み込み完了
document.addEventListener("DOMContentLoaded", () => {
console.log("DOM 構築完了、ここで初期化してOK");
});タイマーとアニメーション:setTimeout / setInterval / requestAnimationFrame
これらは「イベントと実行モデル」の延長として押さえておきたいブラウザAPIです。
setTimeout / setInterval
const id = setTimeout(() => {
console.log("1秒後に1回だけ");
}, 1000);
// 途中でキャンセル
clearTimeout(id);const id2 = setInterval(() => {
console.log("1秒ごとに繰り返し");
}, 1000);
// 止める
clearInterval(id2);- タイマー満了=「タスクキューにコールバックが積まれる」
setIntervalは「積み残し」が出やすいので、
コマ落ちしないアニメーションには後述のrequestAnimationFrameが向いています。
requestAnimationFrame(描画に同期したコールバック)
function loop(timestamp) {
// timestamp: ページロードからのミリ秒(高精度)
console.log("frame:", timestamp);
requestAnimationFrame(loop); // 次のフレームも予約
}
requestAnimationFrame(loop);- ブラウザの再描画タイミング(通常は60fps前後)に合わせて呼ばれる
- スクロール・アニメーション・ゲームなど、滑らかな描画 が必要な時に使う
代表的なブラウザAPI
「これから詳しく学ぶときの見取り図」として、よく使うWeb APIを整理します。
ネットワーク系
fetch(url, options):- HTTPリクエストを送るモダンAPI(Promiseベース)
response.json(),response.text()などで結果を取り出す
-(古い)XMLHttpRequest
ストレージ・状態管理
localStorage:- ブラウザに永続的なキー値ストレージ(文字列のみ)
- タブを閉じても残る
sessionStorage:- タブ(セッション)単位のストレージ
- タブを閉じると消える
localStorage.setItem("username", "Taro");
const name = localStorage.getItem("username");
localStorage.removeItem("username");ウィンドウ・ナビゲーション
location:- 現在のURL(
location.href,location.pathnameなど) location.href = "..."で遷移
- 現在のURL(
history:- 戻る・進む(
history.back(),history.forward()) - SPA で
pushState/replaceStateを使うことも多い
- 戻る・進む(
navigator:- ユーザーエージェント・言語・オンライン状態など
その他 ざっくり
Canvas API(<canvas>の2D描画)Web Audio API(音声処理)Geolocation API(位置情報:HTTPSのみ)WebSocket(双方向通信)IntersectionObserver(要素がビューポートに入ったかどうか)
全部を一気に覚える必要はなく、「こういうジャンルがある」とだけ押さえておけば十分です。
コメント