JS では、イベント ハンドラーが呼び出される順序を実際に制御することはできませんが、慎重に委譲し、適切に配置されたリスナーを使用すれば可能です。
委任は、イベント モデルの最も強力な機能の 1 つです。ご存じかもしれませんが、ご存知かもしれませんが、JS では、イベントは dom の一番上に渡され、そこからイベントが適用される要素に伝播されます。したがって、グローバル オブジェクトにアタッチされたイベント リスナーが、要素自体にアタッチされたリスナーより前にそのハンドラーを呼び出すのは当然のことです。
window.addEventListener('click',function(e)
{
e = e || window.event;
var target = e.target || e.srcElement;
console.log('window noticed you clicked something');
console.log(target);//<-- this is the element that was clicked
}, false);//<-- we'll get to the false in a minute
ハンドラ内のイベント オブジェクトに実際にアクセスできることに注意してください。この場合、イベント オブジェクトをそのままにしておいたので、ターゲットまで伝播し続けます。その途中で、次のようなものに遭遇する可能性があります。
document.getElementById('container').addEventListener('click', function(e)
{
e = e || window.event;
var target = e.target || e.srcElement;
if (target.tagName.toLowerCase() !== 'a' || target.className.match(/\bclickable\b/))
{
return e;//<return the event, unharmed
}
e.returnValue = false;
if (e.preventDefault)
{
e.preventDefault();
}
}, false);
現在、このハンドラーは、ウィンドウ レベルのリスナーがそのヘルパーを呼び出した後に呼び出されます。今回は、クリックされた要素にクラスがない場合、または要素がリンクの場合、イベントが変更されます。clickable
イベントはキャンセルされますが、まだ生きています。イベントは dom のさらに下に自由に伝播できるため、次のようなことが発生する可能性があります。
document.getElmentById('form3').addEventListener('click',function(e)
{
e = e || window.event;
if (e.returnValue === false || e.isDefaultPrevented)
{//this event has been changed already
//do stuff, like validation or something, then you could:
e.cancelBubble = true;
if (e.stopPropagation)
{
e.stopPropagation();
}
}
}, false);
ここでは、 を呼び出すことstopPropagation
で、イベントが強制終了されます。イベントがすでに変更されていない限り、dom のさらに下のターゲットに伝播することはできません。そうでない場合、イベント オブジェクトは、何も起こらなかったかのように、DOM をさらに下に移動します。
ターゲット ノードに到達すると、イベントは 2 番目のフェーズであるバブル フェーズに入ります。DOM の奥深くまで伝播するのではなく、トップ レベルに戻ります (ディスパッチされたグローバル オブジェクトまで、どこから来たのかなど)。
バブル段階では、伝播段階と同じルールがすべて適用されますが、その逆のみです。イベント オブジェクトは、最初にターゲット要素に最も近い要素に遭遇し、最後にグローバル オブジェクトに遭遇します。
ここには、これに関する便利で明確な図がたくさんあります。私はそれを良い 'ol quirksmode よりもうまく表現することはできません.
結論: 2 つのイベント リスナーを扱う場合は、両方を異なるレベルにアタッチして、好きなようにキューに入れます。
両方が呼び出されることを保証したい場合は、最後に呼び出されるハンドラーでのみイベントの伝播を停止します。
同じイベントの同じ要素/オブジェクトにアタッチされた 2 つのリスナーがある場合、最初にアタッチされたリスナーが最初に呼び出されなかったという状況に遭遇したことはありません。
それだけです、私は理にかなっていることを願って、ベッドに向かいます