2017-11-24 12 views
1

親要素のイベントが子イベントの前に発生するように見える私のコードでは、奇妙なバグを乗り越えていました。つまり、e.stopPropagation()は何の効果もありませんでした。子要素の前に親要素のイベントが子孫セレクタにバインドされていると、なぜそれが発生するのですか?

デモ:

$(document).ready(function() { 
 

 
    // Binding directly to the elements 
 
    $(".red1").on("click", function(e) { 
 
    alert("Clicked red1"); 
 
    }); 
 
    $(".green1").on("click", function(e) { 
 
    alert("Clicked green1"); 
 
    e.stopPropagation(); 
 
    }); 
 

 
    // Binding the child from a descendant selector 
 
    $(".red2").on("click", function(e) { 
 
    alert("Clicked red2"); 
 
    }); 
 
    $("body").on("click", ".green2", function(e) { 
 
    alert("Clicked green2"); 
 
    e.stopPropagation(); 
 
    }); 
 

 
});
.red1, 
 
.red2 { 
 
    display: inline-block; 
 
    width: 200px; 
 
    height: 200px; 
 
    background-color: #800; 
 
} 
 

 
.green1, 
 
.green2 { 
 
    display: inline-block; 
 
    width: 100px; 
 
    height: 100px; 
 
    background-color: #080; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 

 
<div class="red1"> 
 
    <div class="green1"></div> 
 
</div> 
 

 
<div class="red2"> 
 
    <div class="green2"></div> 
 
</div>

  • 左側にある緑色の四角形をクリックすると、期待どおりに動作し、1つのアラートが表示されます。
  • 右側の緑色の四角形をクリックすると、親イベントが発生し、その後に子イベントが発生します。

私は、これは私の部分でバインディングがどのように機能するのか誤解していると仮定していますが、なぜこのような順序で発生しているのかを頭に浮かべることはできません。

これはなぜ起こっているのですか?

+2

あなたが委任されたイベントハンドラを使用しているからです。これは、イベントが発生するためには '.red2'をバブルしなければならないことを意味します(したがって、 'parent'イベントハンドラが起動します)、発信者が' .green2'であるかどうかを確認し、委任されたイベントハンドラ実行される。この動作を避けるには、委譲されたイベントハンドラを使用しないでください。親の '.red'要素にすべてのイベントを配置し、発信者を自分で確認してください。 –

+0

@RoryMcCrossanああ、子孫セレクタを使用したバインディングは親要素に効果的にバインドされ、その後、起動されるたびにイベントの発生元を確認します。 – DBS

+0

Roryが言ったことに基づいて展開を並べ替えるには、緑色のdivが '.red2'の内部にあるため、' .red2'が最初に起動されていますが、 '.green2'はクリックイベントが ''要素までバブルすると、「起動」されます。その伝播には少し時間がかかります(違いはありませんが、違いを見るには十分です)。 – Jhecht

答えて

2

問題は、委任されたイベントハンドラを使用しているためです。

これは、イベントが発生するためには、指定された親要素(あなたの場合はbody)までバブルアップする必要があることを意味します。イベントが.red2を通過すると、その要素に割り当てられた静的ハンドラが起動します。委任されたイベントハンドラは、イベント発信元が.green2かどうかを確認します。それが委任された場合、イベントハンドラが実行されます。これが、親ハンドラが最初に起動する理由です。この動作を回避するために

、あなたは彼らが非常に有用であることは必ずしも可能ではないとする、委任イベントハンドラを避けるため、または親要素の上にすべてのイベントを配置し、このように、手動で発信元を確認することができ、次のいずれか

$(".red2").on("click", function(e) { 
 
    if ($(e.target).is('.green2')) { 
 
    alert("Clicked green2"); 
 
    e.stopPropagation(); 
 
    } else { 
 
    alert("Clicked red2"); 
 
    } 
 
});
.red1, 
 
.red2 { 
 
    display: inline-block; 
 
    width: 200px; 
 
    height: 200px; 
 
    background-color: #800; 
 
} 
 

 
.green1, 
 
.green2 { 
 
    display: inline-block; 
 
    width: 100px; 
 
    height: 100px; 
 
    background-color: #080; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 

 
<div class="red2"> 
 
    <div class="green2"></div> 
 
</div>

関連する問題