2016-08-04 1 views
0

委任されたイベントを使用する場合、一致するすべての要素が、ターゲットからバブルアップしてイベントをトリガーします。 DIV-4のトリガーをクリックhttps://learn.jquery.com/events/event-delegation/とHTMLとJS以下に参照のうえに基づいてevent.stopPropagation()は委任されたイベントで複数の一致する要素を停止するのはなぜですか?

、それはバブルアップとして、そのすべての先祖(DIV-1、DIV-2、DIV-3、体)のイベントをクリックしてください。 :not(#div-three)

ここでは、div 4をクリックすると3つのアラートがトリガーされます。 div-four、div-two、div-oneの場合div-four

  1. クリックして、トリガーdiv-fourからのイベントをクリックします。

    は、私は何が起こることは、このようなものだと思います。

  2. div-fourイベントバブルをdiv-threeに、div-threeからイベントをトリガーしました。
  3. div-fourイベントバブルをdiv-twoに、div-twoからイベントをトリガーしました。
  4. div-fourイベントバブルをdiv-oneに、div-oneからイベントをトリガーしました。
  5. div-fourイベントバブルをbodyに変更するには、bodyからイベントをトリガーします。イベントハンドラが実行されます。報告target:div-four|current:div-four
  6. div-three(ステップ2から)イベントバブルはbodyまでバブルします。イベントハンドラを起動しません。
  7. div-two(ステップ3から)イベントバブルはbodyにバブルします。イベントハンドラが実行されます。報告target:div-four|current:div-two
  8. div-one(ステップ4から)イベントバブルはbodyにバブルします。イベントハンドラが実行されます。報告target:div-four|current:div-one

event.stopPropagation()は、イベントハンドラで呼び出された場合、div-fourイベントがステップ5でバブリングを停止する(body上記のバブルには何もありませんが、とにかくが。)しかし、イベントが段階的にトリガ2,3,4まだすべき存在し、バブルアップするので、手順6,7,8は引き続き継続されます。

ただし、これは当てはまりません。次のhttps://jsfiddle.net/bLw7ch50/では、event.stopPropagation()のコメントを外した後、警告が1つだけ表示されます(target:div-four|current:div-four)。だから私はおそらくどこかで間違っている。私の理解に何が間違っていますか?

HTML:

<body> 
    <div id="div-one"> 
    1st div 
    <div id="div-two"> 
     2nd div 
     <div id="div-three"> 
     3rd div 
     <div id="div-four"> 
      4th div 
     </div> 
     </div> 
    </div> 
    </div> 
    <br/> 
    <br/> 
    <div id="output"> 
    </div> 
</body> 

はCSS:

div { 
    border: 1px solid; 
} 

(jquery1.9.1付き)Javascriptの

$(document).ready(function() { 
    $("body").on("click", ":not(#div-three)", function(event) { 
    var event_target = $(event.target).attr("id"); 
    var event_current = $(event.currentTarget).attr("id"); 
    $("#output").append("target:" + event_target + 
         "|current:" + event_current + "<br/>"); 
    alert("target:" + event_target + 
      "|current:" + event_current); 
    // Commented out in https://jsfiddle.net/bLw7ch50/1/, exists in https://jsfiddle.net/bLw7ch50 
    event.stopPropagation(); // When this line is here, all other events stop 
    }); 
}); 
+1

...デリゲートされたイベントが発生すると、そのイベントはデリゲートターゲットに伝播する必要があります。途中のハンドラで伝播を停止すると、伝播しません。 –

+0

..「ボディ」に伝播した後でも、それ以上の伝播はありませんか?イベントが再び 'body'に伝わると言っていますか? – Eric

+0

これは、ドキュメントに一度伝搬した後、再び元に戻ります。間にある各要素で再び開始されません。イベントは1つだけです。それを止めれば停止します。 –

答えて

1

これは、すべてのjQueryのイベントの代表団の中に起こっている、それは何の関係もありませんjQueryは通常のイベントで何が起こるかを模倣しようとしています。

通常のイベントハンドラでは、stopPropagationというイベントが発生しても、そのイベントはツリーから破棄されず、同じイベントタイプのハンドラを持つ祖先はそれを受信しません。これは、イベント委譲を使用するときに、要素に対してイベントハンドラを呼び出す必要があるかどうかを決定するために使用されるのと同じロジックです。

委任を使用してイベントをバインドすると、デリゲートターゲットに1つのイベントのみがバインドされます。イベントハンドラ(イベントハンドラ、jQueryの内部イベントハンドラではありません)がトリガされると、jQueryは元のイベントターゲットとデリゲートターゲットの間にあった要素を調べ、セレクタに基づいてそれらのフィルタをフィルタリングし、元のイベントターゲットをデリゲートターゲットに追加します。それらのハンドラのいずれか1つがstopPropagationである場合、適格なイベントターゲットのリスト内の他の要素は呼び出されたハンドラを持たない。このプロセスで追加のイベントは発生しません。

このシステムでは、他の委任イベントも考慮されます。あなたが最初のボックスをクリックした場合

$(document).on('click', '.box1', function() { 
 
    console.log('first box1 handler'); 
 
}); 
 

 
$(document).on('click', '.box1', function (e) { 
 
    console.log('second box1 handler'); 
 
    e.stopPropagation(); 
 
}); 
 
$(document).on('click', '.box2', function() { 
 
    console.log('first box2 handler'); 
 
}); 
 

 
$(document).on('click', '.box2', function (e) { 
 
    console.log('second box2 handler'); 
 
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<div class="box1"> 
 
<div class="box1"> 
 
<div class="box1"> 
 
<div class="box1"> 
 
click here to begin 
 
</div> 
 
</div> 
 
</div> 
 
</div> 
 
<div class="box2"> 
 
<div class="box2"> 
 
<div class="box2"> 
 
<div class="box2"> 
 
click here to begin without propagation 
 
</div> 
 
</div> 
 
</div> 
 
</div>

あなただけの最初のハンドラと、我々は最も内側のdivを伝搬停止したため、一度と呼ばれる第二のハンドラを取得します。 stopPropgationを使用し、stopImmediatePropagationを使用していないため、両方とも呼び出されます。 2番目のボタンをクリックすると、両方のハンドラが各ボックスdivに対して1回だけ正しい順序で呼び出されます。


残念ながら、これをサポートするためのドキュメントが見つかりませんでした。

関連する問題