イベントモデル
イベントと言えば、Netscape と Microsoft の間の「ブラウザ戦争」に遡ります。当時はイベントモデルの標準が存在せず、両社の実装がデファクトスタンダードとなっていました。 Netscape は Navigator に「イベント キャプチャ」イベント システムを実装しましたが、Microsoft は基本的に反対のイベント システム「イベント バブリング」を IE に実装しました。これら 2 つのシステムの違いは、イベントが発生したとき、そのイベントを処理 (応答) する際の関連要素の優先順位が異なることです。
次の例は、これら 2 つのイベント メカニズムの違いを示しています。ドキュメントの構造が次のとおりであるとします。
>この3つのため 要素が入れ子になっているので、aをクリックすると実際にはspanとdivをクリックします。言い換えれば、3 つの要素すべてにクリック イベントを処理する機会が必要です。イベント キャプチャ メカニズムでは、このクリック イベントの処理の優先順位は次のとおりです。イベント バブリング メカニズムでは、このクリック イベントの処理の優先順位は次のとおりです。
その後、W3C 仕様ではブラウザがキャプチャとバブリングの両方のメカニズムをサポートすることが要求され、開発者がイベントを登録するステージを選択できるようになりました。したがって、イベントを登録するには次の標準的な方法があります。
target.addEventListener(type,listener, useCapture Optional);
ここで:
◆ type: string を示します。監視するイベントの種類
◆listener: 指定したイベント発生時に通知できるリスナーオブジェクト(JavaScript関数)
◆ useCapture: ブール値、キャプチャフェーズに登録するかどうか
実際のアプリケーション開発では、IE との互換性を確保するため (キャプチャをサポートしていないため)、useCapture を false に指定することが一般的です (デフォルト値も false)。つまり、上記の単純な例では、イベントをバブリング ステージに登録するだけです。応答の順序は次のとおりです。
バブリングの副作用
上で述べたように、IE のバブリング イベント モデルは基本的にデファクトスタンダードとなっています。しかし、泡立ちには副作用があります。
引き続き前のドキュメント構造を例として取り上げ、それがインターフェイス内のメニュー項目であると仮定すると、ユーザーのマウスが div から離れたときにメニューを非表示にする必要があります。そこで、div に Mouseout イベントを登録しました。ユーザーが div からマウスを離すと、すべてが正しいことになります。そして、ユーザーのマウスが a または Span から離れると、問題が発生します。イベント バブリングにより、これら 2 つの要素から送出されるマウスアウト イベントが div に伝播され、マウスが div から離れなくなり、メニューが事前に非表示になるためです。
もちろん、バブリングによる副作用を避けるのは難しくありません。たとえば、div 内の各要素のマウスアウト イベントを登録し、.stopPropagation() メソッドを使用してイベントがさらに広がるのを防ぎます。 IE の場合、イベント バブルをキャンセルするには、イベント オブジェクトの cancelBubble プロパティを false に設定する必要があります。ただし、これは依然として、ブラウザーの非互換性の問題に自分で対処するという古い道に戻ります。
最適化計画
バブリングの副作用を回避するために、jQuery は、mouseover と Mouseout の代わりに、mouseenter と Mouseleave イベントを提供します。
以下は、mouseenter と Mouseleave のサポートを提供する jQuery の内部関数 insideElement からの抜粋です。コメントは参考のためにのみ翻訳されています。
コードをコピー
var insideElement = function(event) {
// jQuery.event.special.mouseenter にマウス(over|out) がまだ存在するかどうかを確認し、同じ親要素内での MouseLeave ハンドラー
varparent =event.popularTarget;
// 正しいイベント タイプを設定します
event.type =event.data;
// Firefox は、XUL を RELATEDTarget に割り当てる場合があります。要素
// この要素では、parentNode 属性にアクセスできません
try {
// Chrome も同様ですが、parentNode 属性にはアクセスできます
// しかし、結果は null
if (parent &&parent !== document && !parent.parentNode ) {
return
}
// DOM ツリーを上へ
while (parent &&parent !== this ) {
parent =parent.parentNode;
}
if (parent !== this ) {
// 実際に子要素以外にある場合は、イベント
jQuery を処理します。 .event.handle .apply( this, argument );
}
// マウスはおそらく XUL 要素上に置かれているため、要素は残されたと想定されます
} catch(e) { }
},
結論
jQuery では、mouseenter イベントと Mouseleave イベントを使用して、イベント バブリングの副作用を回避できます。
原文: http://www.ituring.com.cn/article/420