<body>
<div id="wrap">
<p class="hint">
<a href="#">クリックしてください</a>
</p>
</div>
</body>
タグごとにイベントが定義されている場合、 <a>
タグをクリックすると、 <div>
と<p>
タグにバインドされたイベントもトリガーされることがわかります。この質問に答えるために、Microsoft と Netscape は、イベント キャプチャとイベント バブリングという 2 つの異なる概念を提案しました。
- イベント キャプチャ: Microsoft Corporation によって提案された、イベントはドキュメント ルート ノード (ドキュメント オブジェクト) からターゲット ノードに流れ、途中でターゲット ノードの各親ノードを通過し、ターゲット ノードに到達するまでこれらのノードでキャプチャ イベントをトリガーします。イベントの;
- イベント バブリング: Netscape によって提案されたもので、イベント キャプチャとは逆に、イベントはターゲット ノードからドキュメントのルート ノードに流れ、途中でターゲット ノードの親ノードを通過し、到達するまでこれらのノードでキャプチャ イベントをトリガーします。ドキュメント ノードのルート。全体のプロセスは、水中の気泡のようなもので、水の底から上に移動します。
ヒント: 上記のターゲット ノードは、イベントをトリガーするノードを指します。
その後、標準を統一するために、W3C は、次の図に示すように、イベント キャプチャとイベント バブリングを組み合わせるという妥協案を採用しました。
イベントキャプチャ
イベント キャプチャ フェーズでは、イベントは DOM ツリーの最外層から開始され、ターゲット ノードの各親ノードを順番に通過し、イベントのターゲット ノードに到達するまで親ノードでイベントをトリガーします。上図のコードを例にとると、 <a>
タグをクリックすると、 document -> div -> p -> a
の順にイベントが<a>
タグに渡されます。
サンプルコードは次のとおりです。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>JavaScript</title>
<style type="text/css">
div, p, a {
padding: 15px 30px;
display: block;
border: 2px solid #000;
background: #fff;
}
</style>
</head>
<body>
<div id="wrap">DIV
<p class="hint">P
<a href="#">A</a>
</p>
</div>
<script>
function showTagName() {
alert("事件捕获: " + this.tagName);
}
var elems = document.querySelectorAll("div, p, a");
for (let elem of elems) {
elem.addEventListener("click", showTagName, true);
}
</script>
</body>
</html>
上記のコードを実行し、最も内側の<a>
タグをクリックすると、実行結果が次の図に表示されます。
イベントバブリング
イベント バブリングは、イベント キャプチャとは正反対です。イベント バブリングは、ターゲット ノードから始まり、親ノードに沿って上昇し、水底の泡のように、ドキュメント ルート ノードまで親ノードでイベントをトリガーします。必ず上がります。
サンプルコードは次のとおりです。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JavaScript</title>
<style type="text/css">
div, p, a {
padding: 15px 30px;
display: block;
border: 2px solid #000;
background: #fff;
}
</style>
</head>
<body>
<div onclick="alert('イベントバブリング:' + this.tagName)">DIV
<p onclick="alert('イベントバブリング:' + this.tagName)">P
<a href="#" onclick="alert('イベントバブリング:' + this.tagName)">A</a>
</p>
</div>
</body>
</html>
上記のコードを実行し、最も内側の<a>
タグをクリックすると、実行結果が次の図に表示されます。
イベントのキャプチャとバブリングを防ぐ
イベント キャプチャとイベント バブリングを理解すると、この機能が使いにくいことがわかります.たとえば、特定のノードにイベントをバインドし、クリックしたときにこのイベントをトリガーしたかった.その結果、イベント バブリングにより、イベントこのノードの子要素がトリガーされます。これを防ぐにはどうすればよいでしょうか。
イベントのキャプチャとイベントのバブリングを防ぐために、JavaScript で stopPropagation() メソッドが提供されます。構文は次のとおりです。
event.stopPropagation();
Note: stopPropagation() will prevent event capture and event bubbling, but it cannot prevent the default behavior of the label. たとえば、リンクをクリックすると、対応する Web ページを開くことができます。
サンプルコードは次のとおりです。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JavaScript</title>
<style type="text/css">
div, p, a {
padding: 15px 30px;
display: block;
border: 2px solid #000;
background: #fff;
}
</style>
</head>
<body>
<div id="wrap">DIV
<p class="hint">P
<a href="#">A</a>
</p>
</div>
<script>
function showAlert(event) {
alert("あなたは" + this.tagName + "タグをクリックしました。");
event.stopPropagation();
}
var elems = document.querySelectorAll("div, p, a");
for(let elem of elems) {
elem.addEventListener("click", showAlert);
}
</script>
</body>
</html>
In addition, you can also use the stopImmediatePropagation() method to prevent other event handlers for the same event on the same node. たとえば、特定のノードに対して複数のクリック イベントが定義されている場合、イベントがトリガーされると、これらのイベントはイベント ハンドラの 1 つが stopImmediatePropagation() メソッドを使用する場合、残りのイベント ハンドラは実行されません。
stopImmediatePropagation() メソッドの構文は次のとおりです。
event.stopImmediatePropagation();
サンプルコードは次のとおりです。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>JavaScript</title>
<style type="text/css">
div, p, a {
padding: 15px 30px;
display: block;
border: 2px solid #000;
background: #fff;
}
</style>
</head>
<body>
<div onclick="alert('あなたは'+this.tagName+'タグをクリックしました')">DIV
<p onclick="alert('あなたは'+this.tagName+'タグをクリックしました')">P
<a href="#" id="link">A</a>
</p>
</div>
<script>
function sayHi() {
alert("イベントの処理1");
event.stopImmediatePropagation();
}
function sayHello() {
alert("イベントの処理2");
}
//idがlinkのタグに複数のクリックイベントを定義する
var link = document.getElementById("link");
link.addEventListener("click", sayHi);
link.addEventListener("click", sayHello);
</script>
</body>
</html>
特定のイベントには、リンクをクリックしたとき、指定したページに自動的にジャンプしたとき、送信ボタンをクリックしたとき、サーバーにデータを送信したときなど、デフォルトのアクションが関連付けられています。このようなデフォルト操作が発生することを望まない場合は、 preventDefault() メソッドを使用してそれを防ぐことができます. 構文は次のとおりです:
event. preventDefault();
サンプルコードは次のとおりです。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>JavaScript</title>
</head>
<body>
<a href="https://it-kiso.com/" id="link">リンク</a>
<script>
var link = document.getElementById("link");
link.addEventListener('click', function(event){
event.preventDefault(); // リンクのジャンプを防止する
});
</script>
</body>
</html>
注: IE9 以下のバージョンは preventDefault() メソッドをサポートしていません。IE9 以下のブラウザーでは、 event.returnValue = false;
を使用できます。