ボタンのクリック、リンクのタップ、カードの選択など、クリックイベントは Web アプリケーションで最も基本的なユーザー操作です。JavaScript の addEventListener を使えば、任意の HTML 要素にクリック時の処理を設定できます。
この記事でわかること
・addEventListener でクリックイベントを設定する方法
・onclick 属性・onclick プロパティとの違い
・event オブジェクトの活用(target・currentTarget・preventDefault)
・バブリングとキャプチャリングの仕組み
・イベント委任(Event Delegation)で動的要素に対応する方法
・once・passive オプション
・ダブルクリック・右クリックの検出
・トグル切り替え・モーダル開閉・連打防止の実務パターン
・addEventListener でクリックイベントを設定する方法
・onclick 属性・onclick プロパティとの違い
・event オブジェクトの活用(target・currentTarget・preventDefault)
・バブリングとキャプチャリングの仕組み
・イベント委任(Event Delegation)で動的要素に対応する方法
・once・passive オプション
・ダブルクリック・右クリックの検出
・トグル切り替え・モーダル開閉・連打防止の実務パターン
addEventListener でクリックイベントを設定する
HTML
<button id="myBtn">クリック</button>
JavaScript
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 つのみ | ★ 非推奨 |
addEventListener: 複数登録できる
const btn = document.getElementById("myBtn");
// 2つのリスナーを同じ要素に登録できる
btn.addEventListener("click", () => console.log("処理A"));
btn.addEventListener("click", () => console.log("処理B"));
// クリック時: "処理A" → "処理B"(両方実行される)
onclick プロパティ: 後から上書きされる
const btn = document.getElementById("myBtn");
btn.onclick = () => console.log("処理A");
btn.onclick = () => console.log("処理B"); // 処理Aが消える
// クリック時: "処理B" のみ
現代の JavaScript では常に
addEventListener を使いましょう。複数のリスナーを同じ要素に登録でき、once や passive などのオプションも設定できます。event オブジェクトを活用する
コールバック関数の引数として event オブジェクトが渡されます。クリック位置、クリックされた要素、デフォルト動作の抑止などに使います。
| プロパティ / メソッド | 説明 |
|---|---|
event.target |
実際にクリックされた要素 |
event.currentTarget |
リスナーが登録されている要素 |
event.preventDefault() |
デフォルト動作を抑止(リンク遷移・フォーム送信など) |
event.stopPropagation() |
イベントの伝播(バブリング)を停止 |
event.clientX / clientY |
クリック位置(ビューポート基準) |
event.button |
押されたボタン(0=左, 1=中, 2=右) |
target と currentTarget の違い
<div id="parent"> <button id="child">クリック</button> </div>
JavaScript
document.getElementById("parent").addEventListener("click", (e) => {
console.log("target:", e.target.id); // "child"(実際にクリックされた要素)
console.log("currentTarget:", e.currentTarget.id); // "parent"(リスナーが付いた要素)
});
preventDefault でデフォルト動作を抑止する
JavaScript
// リンクのクリックでページ遷移を防ぐ
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>
JavaScript
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"(子→親の順に伝播)
stopPropagation でバブリングを停止
document.getElementById("btn").addEventListener("click", (e) => {
e.stopPropagation(); // 親要素への伝播を停止
console.log("btn のみ実行");
});
// ボタンをクリック → "btn のみ実行"(inner, outer は実行されない)
イベント委任(Event Delegation)
動的に追加される要素にもイベントを適用するには、親要素にリスナーを 1 つだけ設定し、event.target で判定するイベント委任パターンが有効です。
JavaScript
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 |
キャプチャフェーズでリスナーを実行 | 親要素で先にイベントを処理 |
JavaScript
// 1回だけ実行されるリスナー
document.getElementById("welcomeBtn").addEventListener("click", () => {
console.log("ようこそ!(この処理は1回だけ)");
}, { once: true });
ダブルクリック・右クリックの検出
| イベント | 検出する操作 |
|---|---|
"click" |
左クリック(シングル) |
"dblclick" |
ダブルクリック |
"contextmenu" |
右クリック(コンテキストメニュー) |
"auxclick" |
中クリック(ホイールクリック) |
JavaScript
// ダブルクリックで編集モードに切り替え
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)
JavaScript
function handleClick() {
console.log("クリック!");
}
const btn = document.getElementById("myBtn");
// 登録
btn.addEventListener("click", handleClick);
// 削除(同じ関数参照を渡す必要がある)
btn.removeEventListener("click", handleClick);
removeEventListener は同じ関数参照を渡さないと削除できません。匿名関数(アロー関数を直接書く)で登録した場合は削除できないため、削除が必要なリスナーは名前付き関数で定義してください。実務でよく使うパターン
クラスのトグル切り替え
JavaScript
document.getElementById("toggleBtn").addEventListener("click", () => {
document.getElementById("menu").classList.toggle("is-open");
});
モーダルの開閉
JavaScript
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");
});
連打防止(デバウンス)
JavaScript
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 の使い方
よくある質問
QaddEventListener と onclick はどちらを使うべきですか?
A
addEventListener を使いましょう。onclick プロパティは 1 つしか登録できず後から上書きされます。addEventListener は複数登録でき、once / passive オプションも使えます。Qevent.target と event.currentTarget の違いは?
A
target は実際にクリックされた要素、currentTarget はリスナーが登録されている要素です。イベント委任で親要素にリスナーを付けた場合、target は子要素、currentTarget は親要素になります。Q動的に追加した要素にクリックイベントが効きません。
AaddEventListener は呼び出し時点で存在する要素にしか設定されません。動的要素にはイベント委任を使ってください。親要素にリスナーを設定し、
e.target.matches(".class") でクリックされた要素を判定します。Q1回だけ実行されるクリックイベントを設定するには?
A
addEventListener("click", fn, { once: true }) で 1 回実行後に自動的にリスナーが削除されます。従来の removeEventListener を自分で呼ぶ方法より簡潔です。Qスマホでクリックイベントが反応しません。
Aスマホでは
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 オプションを使いこなすことで、効率的でメンテナブルなコードを書けるようになります。