イベント キャプチャの実装上の問題 W3C DOM Level2 イベント モデル仕様では、DOM ツリー内のイベントの伝播プロセス (ルート ノードからターゲット ノードまで) が 2 つに分かれています。ステージ: キャプチャーとバブリング。次の図は、プロセス全体を大まかに示しています。
(W3C より)
キャプチャ イベントを作成する場合は、W3C イベント モデルをサポートするブラウザで、 addEventListener の 3 番目の要素 3 つのパラメーターを true に設定するだけです。例:
document.getElementById('foo) ').addEventListener ('click',function(){alert('Hello, world!');},true);
少し前にイベントキャプチャを理解したかったので理解しました。イベント キャプチャは、Firefox 2、Windows 上の Safari 3、および Opera 9 で実行されました (もちろん、IE はイベント キャプチャをサポートしていないため...)。実験の原理を次の図に示します。 🎜>
ID は div1 で、div2 の両方の要素はキャプチャフェーズでイベントハンドラー関数にバインドされているため、次のようになります:
#div1 (青い領域) がクリックされると、アラートが表示されます。 "div1"
#div2 をクリックすると (黄色の領域)、最初に "div1" がアラートされ、次に "div2" がアラートされる必要があります。これは、イベントのキャプチャ段階でイベントがルート要素から下方向に伝播されるためです。 #div1 は #div2 の親要素であり、自然にバインドされています。#div1 のクリック イベントも、#div2 のクリック イベントの前に実行されます。
ただし、上記のアイデアは Windows の Firefox 2 と Safari 3 でのみ機能します。Opera 9 では、次のようになります。
#div1 (青い領域) をクリックしても、何も起こりません。
#div2 (黄色の領域) をクリックすると、「div1」がアラートされ、その後は何も起こりません
Opera 9 では、対象要素 (TargetElement) のクリック イベントが実行されないことがわかります。 Realazy の指導により (orz...)、「イベント キャプチャの説明」という記事を見つけ、Opera での実装が正しいことがわかりました。この記事には次のような文章があります:
DOM 仕様では、イベントのキャプチャはターゲットに到達する前にイベントを検出することが目的であるため、ターゲットで起動すべきではないと述べています。 Gecko と Safari のバグのため、主に Firefox またはその他の Gecko ベースのブラウザでテストされている Web コンテンツは、キャプチャ リスナーがターゲットで起動することを期待していることがありますが、Opera 7、8、および現在のリリース 9 では、その実装が正しいため失敗します。
一般的な考え方は次のとおりです: DOM 仕様では、イベントのキャプチャの目的はターゲット要素に到達する前にイベントを監視することであるため、イベントのキャプチャはターゲット要素で実行すべきではないと述べています。 Firefox と Safari の実装にはバグがあります。
W3C の DOM イベント仕様の元の言葉を見てみましょう:
キャプチャする EventListener は、登録されている EventTarget に直接ディスパッチされるイベントによってはトリガーされません。
したがって、In。イベント伝播全体の実行順序は次のとおりです:
親要素 (存在する場合) のすべてのキャプチャ イベントは上から下に実行されます
ターゲット要素のバブリング イベント (存在する場合)
親要素内のすべてのバブリング イベント (存在する場合) は下から上に実行されます
これを理解した後は、少なくともまだはイベント キャプチャを使用しない方が良いかもしれません。
IE の高度なイベント処理モデルの問題
バインディングの重複 IE には addEventListener はありませんが、独自のattachEvent、いわゆる Microsoft モデルもあります。この 2 つの実装は基本的に同じですが、attachEvent の最初のパラメータ (イベント タイプ) には「on」を追加する必要がありますが、addEventListener では追加する必要がありません。また、attachEvent はイベント キャプチャをサポートしていないため、3 番目のパラメータはありません。
しかし、attachEvent にはバインディング イベントが繰り返されるという重大な問題があります。 (これは JavaScript の ppk から学びます)
例:
function SayHello(){
alert('Hello, world!')
}
// W3C モデル
$('div1').addEventListener( ' click'、sayHello、false);
$('div1').addEventListener('click'、sayHello、false);
// Microsoft モデル
$('div1').attachEvent(' onclick '、sayHello);
$('div1').attachEvent('onclick'、sayHello);
W3C モデルでは、同じイベント ハンドラー関数のバインディングは無視されます。つまり、2 番目の $('div1').addEventListener('click',sayHello,false); は無視されます。
Microsoft モデルでは、2 番目の $('div1').attachEvent('onclick',sayHello); も実行されるため、#div1 をクリックすると、アラート ボックスが 2 回表示されます。さらに、detachEvent 中に、#div1 のクリック イベントからsayHello を完全に削除するには 2 つの detachEvent も必要です。
alertID() を引き続き使用しないのはなぜですか?
これは、IE のイベント モデルの別の欠陥によるものです。このように、W3C モデルでは、alertID で this キーワードがバインドされている要素を参照します。 #div1 または #div2 を置き換えます。
しかし、Microsoft モデルでは、this がサポートされていないと、this.id は未定義になります。これは、現時点で this が window オブジェクトを参照しているためです。