4

useCaptureJavaScript の のパラメータを理解しようとしていますaddEventListener()。ここに私のHTMLがあります:

<div id="wrapper">
    <button id="button">Click me</button>
</div>

これが私のJavaScriptです:

document.getElementById('wrapper').addEventListener('click', function () { console.log('Wrapper capture'); }, true);
document.getElementById('wrapper').addEventListener('click', function () { console.log('Wrapper bubble'); }, false);
document.getElementById('button').addEventListener('click', function () { console.log('Button bubble'); }, false);
document.getElementById('button').addEventListener('click', function () { console.log('Button capture'); }, true);

さて、私は注文が であると予想しましたWrapper capture, Button capture, Button bubble, Button bubble。驚いたことに、ここに私の出力があります:

Wrapper capture
Button bubble
Button capture
Wrapper bubble

2 つのボタン ハンドラが混同されていますか? 他のブラウザーでテストしましたが、Chrome、Firefox、IE10 はすべて同じ動作を示します。私はこれに少し困惑しています。MDNQuirksMode.org、および仕様はすべて、さまざまなフェーズと、キャプチャ フェーズがバブリング フェーズに先行する方法を明確に説明しています。私の小さな実験の結果、Button bubbleハンドラーが私の前に呼び出されるのはButton captureなぜですか?

ここに何が起こっているのかのフィドルがあります:http://jsfiddle.net/Tr7G6/2


// Update ハンドラーをアタッチする順序が重要なようです。

document.getElementById('wrapper').addEventListener('click', function () { console.log('Wrapper capture'); }, true);
document.getElementById('wrapper').addEventListener('click', function () { console.log('Wrapper bubble'); }, false);
document.getElementById('button').addEventListener('click', function () { console.log('Button capture'); }, true);
document.getElementById('button').addEventListener('click', function () { console.log('Button bubble'); }, false);

最初にキャプチャし、2 番目にバブルするようにバインドすると、クロスブラウザーで期待どおりの出力が生成されます。しかし、これはばかげています。この順序が重要なのはなぜですか?

4

1 に答える 1

1

バブリング/キャプチャは、イベントがターゲット要素にバブリング/キャプチャする場合にのみ関連し、イベントがその要素で直接トリガーされた場合には関連しません (これは W3C イベント モデルの「ターゲット フェーズ」です)。「バブル」または「キャプチャ」がない場合click(あなたのイベントの場合)、<button>イベントは追加された順に処理されます。

たとえば、「ラッパー」のリスナーの順序を逆にして、(ボタンではなく) ラッパー要素をクリックすると、同じ動作に気付くでしょう (最初にバブルが起動します)。

// 1. "Wrapper Bubble" 2. "Wrapper Capture"
document.getElementById('wrapper').addEventListener('click', function () { console.log('Wrapper bubble'); }, false);
document.getElementById('wrapper').addEventListener('click', function () { console.log('Wrapper capture'); }, true);

ただし、同じ順序 (キャプチャの前にバブル) を使用し、buttonキャプチャをクリックすると、バブルの前にキャプチャが実行されます。これは、「クリック」イベントが でトリガーされ、button「バブリング」(通常のイベント フロー) の前に DOM を介して「キャプチャ ダウン」されるためです。

これを明確にするのに役立つことを願ってJSBINを作成しました(ただし、混乱を招くだけかもしれません)。「順序付き」ボタン/divは最初のスニペットの順序をトリガーし、「順序なし」ボタンとdivは2番目の順序を使用します。

追加情報については、このSO の回答と W3Cイベント フローのドキュメント、具体的にはTarget Phaseを参照してください。

于 2013-08-07T16:15:30.367 に答える