ボタンのクリック、リンクのタップ、カードの選択など、クリックイベントは Web アプリケーションで最も基本的なユーザー操作です。JavaScript の addEventListener を使えば、任意の HTML 要素にクリック時の処理を設定できます。
・addEventListener でクリックイベントを設定する方法
・onclick 属性・onclick プロパティとの違い
・event オブジェクトの活用(target・currentTarget・preventDefault)
・バブリングとキャプチャリングの仕組み
・イベント委任(Event Delegation)で動的要素に対応する方法
・once・passive オプション
・ダブルクリック・右クリックの検出
・トグル切り替え・モーダル開閉・連打防止の実務パターン
addEventListener でクリックイベントを設定する
<button id="myBtn">クリック</button>
const btn = document.getElementById("myBtn");
btn.addEventListener("click", () => {
console.log("クリックされました");
});
第 1 引数にイベント名("click")、第 2 引数にコールバック関数を渡します。
クリックイベントを設定する 3 つの方法と違い
| 方法 | コード例 | 複数登録 | 推奨度 |
|---|---|---|---|
| addEventListener | el.addEventListener("click", fn) |
○ 可能 | ★★★ 推奨 |
| onclick プロパティ | el.onclick = fn |
× 上書きされる | ★★ |
| HTML 属性 | <button onclick="fn()"> |
× 1 つのみ | ★ 非推奨 |
const btn = document.getElementById("myBtn");
// 2つのリスナーを同じ要素に登録できる
btn.addEventListener("click", () => console.log("処理A"));
btn.addEventListener("click", () => console.log("処理B"));
// クリック時: "処理A" → "処理B"(両方実行される)
const btn = document.getElementById("myBtn");
btn.onclick = () => console.log("処理A");
btn.onclick = () => console.log("処理B"); // 処理Aが消える
// クリック時: "処理B" のみ
addEventListener を使いましょう。複数のリスナーを同じ要素に登録でき、once や passive などのオプションも設定できます。event オブジェクトを活用する
コールバック関数の引数として event オブジェクトが渡されます。クリック位置、クリックされた要素、デフォルト動作の抑止などに使います。
| プロパティ / メソッド | 説明 |
|---|---|
event.target |
実際にクリックされた要素 |
event.currentTarget |
リスナーが登録されている要素 |
event.preventDefault() |
デフォルト動作を抑止(リンク遷移・フォーム送信など) |
event.stopPropagation() |
イベントの伝播(バブリング)を停止 |
event.clientX / clientY |
クリック位置(ビューポート基準) |
event.button |
押されたボタン(0=左, 1=中, 2=右) |
<div id="parent"> <button id="child">クリック</button> </div>
document.getElementById("parent").addEventListener("click", (e) => {
console.log("target:", e.target.id); // "child"(実際にクリックされた要素)
console.log("currentTarget:", e.currentTarget.id); // "parent"(リスナーが付いた要素)
});
preventDefault でデフォルト動作を抑止する
// リンクのクリックでページ遷移を防ぐ
document.querySelector("a.no-navigate").addEventListener("click", (e) => {
e.preventDefault();
console.log("遷移しません");
});
// フォームの送信を防いで独自処理
document.getElementById("myForm").addEventListener("submit", (e) => {
e.preventDefault();
// 非同期送信などの独自処理
});
バブリングとキャプチャリング
クリックイベントは、クリックされた要素から親要素に向かって伝播します(バブリング)。逆に、document から子要素に向かう伝播がキャプチャリングです。
<div id="outer">
<div id="inner">
<button id="btn">クリック</button>
</div>
</div>
document.getElementById("btn").addEventListener("click", () => console.log("btn"));
document.getElementById("inner").addEventListener("click", () => console.log("inner"));
document.getElementById("outer").addEventListener("click", () => console.log("outer"));
// ボタンをクリックすると:
// "btn" → "inner" → "outer"(子→親の順に伝播)
document.getElementById("btn").addEventListener("click", (e) => {
e.stopPropagation(); // 親要素への伝播を停止
console.log("btn のみ実行");
});
// ボタンをクリック → "btn のみ実行"(inner, outer は実行されない)
イベント委任(Event Delegation)
動的に追加される要素にもイベントを適用するには、親要素にリスナーを 1 つだけ設定し、event.target で判定するイベント委任パターンが有効です。
const list = document.getElementById("todoList");
// 親要素に1つだけリスナーを設定
list.addEventListener("click", (e) => {
// クリックされた要素が削除ボタンか判定
if (e.target.matches(".delete-btn")) {
e.target.closest("li").remove();
}
});
// 後から追加した li 内の .delete-btn もイベントが動作する
function addItem(text) {
list.insertAdjacentHTML(
"beforeend",
`<li>${text} <button class="delete-btn">削除</button></li>`
);
}
once・passive オプション
| オプション | 説明 | 用途 |
|---|---|---|
once: true |
1 回実行後に自動的にリスナーを削除 | 初回のみの処理(チュートリアル表示など) |
passive: true |
preventDefault を呼ばないことを宣言 |
スクロール・タッチイベントの最適化 |
capture: true |
キャプチャフェーズでリスナーを実行 | 親要素で先にイベントを処理 |
// 1回だけ実行されるリスナー
document.getElementById("welcomeBtn").addEventListener("click", () => {
console.log("ようこそ!(この処理は1回だけ)");
}, { once: true });
ダブルクリック・右クリックの検出
| イベント | 検出する操作 |
|---|---|
"click" |
左クリック(シングル) |
"dblclick" |
ダブルクリック |
"contextmenu" |
右クリック(コンテキストメニュー) |
"auxclick" |
中クリック(ホイールクリック) |
// ダブルクリックで編集モードに切り替え
document.getElementById("text").addEventListener("dblclick", (e) => {
e.target.contentEditable = true;
e.target.focus();
});
// 右クリックメニューをカスタマイズ
document.getElementById("canvas").addEventListener("contextmenu", (e) => {
e.preventDefault(); // デフォルトの右クリックメニューを抑止
showCustomMenu(e.clientX, e.clientY);
});
リスナーを削除する(removeEventListener)
function handleClick() {
console.log("クリック!");
}
const btn = document.getElementById("myBtn");
// 登録
btn.addEventListener("click", handleClick);
// 削除(同じ関数参照を渡す必要がある)
btn.removeEventListener("click", handleClick);
removeEventListener は同じ関数参照を渡さないと削除できません。匿名関数(アロー関数を直接書く)で登録した場合は削除できないため、削除が必要なリスナーは名前付き関数で定義してください。実務でよく使うパターン
クラスのトグル切り替え
document.getElementById("toggleBtn").addEventListener("click", () => {
document.getElementById("menu").classList.toggle("is-open");
});
モーダルの開閉
const modal = document.getElementById("modal");
const overlay = document.getElementById("overlay");
// 開く
document.getElementById("openBtn").addEventListener("click", () => {
modal.classList.add("is-open");
overlay.classList.add("is-open");
});
// 閉じる(オーバーレイクリック)
overlay.addEventListener("click", () => {
modal.classList.remove("is-open");
overlay.classList.remove("is-open");
});
連打防止(デバウンス)
const submitBtn = document.getElementById("submitBtn");
submitBtn.addEventListener("click", () => {
// ボタンを無効化
submitBtn.disabled = true;
submitBtn.textContent = "送信中...";
// 送信処理(API呼び出しなど)
fetch("/api/submit", { method: "POST" })
.then(res => res.json())
.then(data => {
submitBtn.textContent = "送信完了";
})
.catch(() => {
// エラー時はボタンを再有効化
submitBtn.disabled = false;
submitBtn.textContent = "再送信";
});
});
関連記事
- Event Delegation で効率的にイベントを管理する方法
- イベントを無効化する方法
- 送信ボタンの連続クリックを防ぐテクニック
- ハンバーガーメニューの実装方法
- classList の使い方完全ガイド
- querySelector / querySelectorAll の使い方
よくある質問
addEventListener を使いましょう。onclick プロパティは 1 つしか登録できず後から上書きされます。addEventListener は複数登録でき、once / passive オプションも使えます。target は実際にクリックされた要素、currentTarget はリスナーが登録されている要素です。イベント委任で親要素にリスナーを付けた場合、target は子要素、currentTarget は親要素になります。e.target.matches(".class") でクリックされた要素を判定します。addEventListener("click", fn, { once: true }) で 1 回実行後に自動的にリスナーが削除されます。従来の removeEventListener を自分で呼ぶ方法より簡潔です。click イベントは動作しますが、cursor: pointer が設定されていない非インタラクティブ要素(div・span)では反応しないことがあります。CSS で cursor: pointer を追加するか、button 要素を使ってください。まとめ
JavaScript でクリックイベントを扱う方法を整理しました。
- 基本:
el.addEventListener("click", fn)でリスナーを登録 - event オブジェクト: target・preventDefault・stopPropagation を活用
- バブリング: 子→親に伝播する。stopPropagation で停止可能
- イベント委任: 親要素に 1 つだけリスナーを設定し、動的要素にも対応
- オプション: once(1回のみ)、passive(最適化)、capture(キャプチャフェーズ)
- 削除: removeEventListener には同じ関数参照が必要
クリックイベントは Web アプリのインタラクションの基礎です。イベント委任と once オプションを使いこなすことで、効率的でメンテナブルなコードを書けるようになります。