ホームページ > ウェブフロントエンド > jsチュートリアル > JavaScript イベントのバブリングとキャプチャとブロックの方法の詳細な説明_JavaScript スキル

JavaScript イベントのバブリングとキャプチャとブロックの方法の詳細な説明_JavaScript スキル

WBOY
リリース: 2016-05-16 16:52:37
オリジナル
959 人が閲覧しました

1. 一連のイベント

この問題の原因は非常に単純です。別の要素内にネストされた要素があるとします。

コードをコピー コードは次のとおりです:

---------------------------------
| 要素 1 | ------- |

--------------------- ---- -------

: どちらも onClick イベント ハンドラーを持っています。ユーザーが要素 2 をクリックすると、要素 1 と要素 2 の両方のクリック イベントがトリガーされます。しかし、どのイベントが最初にトリガーされるのでしょうか?どのイベント ハンドラー関数が最初に実行されますか?言い換えれば、一連の出来事の正確な順序は何だったのでしょうか?

2. 2 つのモデル

予想通り、Netscape と Microsoft は、「ブラウザ戦争」の時代に対処するために 2 つの非常に異なるアプローチをとっていました。

Netscape は、要素 1 のイベントが最初に発生することを推奨しています。

Microsoft は、このイベントの順序がバブリング タイプと呼ばれていると主張しています。そのうちの出来事の順序は正反対です。 Explorer ブラウザはバブリング イベントのみをサポートしますが、Mozilla、Opera7、Konqueror は両方をサポートします。古い Opera と iCab はどちらもサポートしていません


3. イベントをキャプチャします

イベントのキャプチャを使用する場合


コードをコピーします

コードは次のとおりです: ---------------| |-----------------
| | --- --------| |---------- |
| |要素 2 / |
| -- ---------- |
| イベントのキャプチャ |
-------------------------- -- ------

: 要素 1 のイベント ハンドラーが最初にトリガーされ、要素 2 のイベント ハンドラーが最後にトリガーされます


4. バブルイベント

バブリングイベントを使用する場合

コードをコピーします

コードは次のとおりです: ---------------| |-----------------| | - ----------| |---------- |
| |
| ----------- |
| イベントバブリング |
-------------------------- -- -------

: 要素 2 の処理関数が最初にトリガーされ、続いて要素 1
がトリガーされます。

5. W3C モデル

W3c は、この戦いで正しい解決策を賢明に選択しました。 w3c イベント モデルで発生するイベントは、まずターゲット要素に到達するまでキャプチャ フェーズに入り、その後バブリング フェーズに入ります

コピー コード


コードは次のとおりです:

--
| | |
| -|
| |
|
| W3C イベント モデル |
-------------------------------------- ------
Web 開発者は、イベント処理関数をキャプチャ フェーズでバインドするかバブリング フェーズでバインドするかを選択できます。これは、最後のパラメータの addEventListener() メソッドによって実現されます。この関数の値が true の場合、キャプチャ フェーズでフェーズ バインド関数が返されます。それ以外の場合は、バブリング フェーズで関数がバインドされます。


コードをコピー とします。コードは次のとおりです。
element1 .addEventListener(' click',doSomething2,true)
element2.addEventListener('click',doSomething,false)

ユーザーが要素 2 をクリックすると、次に何が起こります:

(このイベントはここでの観光客のようなもので、外側から内側へ移動し、トリガーされた主要な要素に徐々に近づき、その後反対方向に去っていきます)

1. クリック イベントは最初にキャプチャ フェーズに入ります (要素 2 の方向に徐々に近づきます)。キャプチャフェーズで要素 2 の祖先要素のいずれかに onclick ハンドラーがあるかどうかを確認します

2. 要素 1 に onclick ハンドラーがあることが判明したため、doSomething2 が実行されます
3. イベントはターゲット自体をチェックします (要素 2) ) ですが、キャプチャフェーズには onclick ハンドラーがありません。さらに処理関数が見つかりました。イベントはバブリング段階に入り始め、要素 2 のバブリング段階にバインドされている関数である doSomething() が自然に実行されます。
4. イベントは要素 2 から離れて、バブリングフェーズ中に祖先要素にハンドラーがバインドされているかどうかを確認します。そのようなケースは存在しないため、何も起こりません
逆のケースは次のとおりです。

コードをコピーしますコードは次のとおりです。
element1.addEventListener('click',doSomething2,false)
element2.addEventListener('click',doSomething,false)

ユーザーが要素 2 をクリックすると、次のことが起こります:
1. イベントをクリックしてキャプチャフェーズに入ります。キャプチャフェーズで要素 2 の祖先要素のいずれかに onclick ハンドラーがあるかどうかを確認しますが、何も見つかりません

2. イベントはターゲット自体を検出します。イベントはバブリングフェーズに入り始め、要素 2 のバブリングフェーズにバインドされた関数が実行されます。 doSomething()
3. イベントがターゲットから離れ始めます。バブリング段階で要素 2 の祖先要素にハンドラー関数がバインドされているかどうかを確認します。要素 1 の
が実行されます。

6. 互換性と従来モード

w3c dom (Document Object Model) をサポートするブラウザーでは、従来のイベント バインディング メソッドは次のとおりです。


コードをコピー コードは次のとおりです。次のように: element1.onclick = doSomething2;
は、デフォルトでバブリング ステージにバインドされているとみなされます

7. バブリングイベントを使用する

バブリング イベントやイベントのキャプチャを意識的に使用する開発者はほとんどいません。彼らが現在作成している Web ページでは、イベントはバブルアップするため、複数の関数によって処理される必要はありません。しかし、マウスを 1 回クリックしただけでさまざまなことが起こる (バブリングにより複数の機能が実行される) ため、ユーザーが混乱することがあります。ほとんどの場合、処理関数は互いに独立している必要があります。ユーザーが要素をクリックしたときに何が起こるか、そしてユーザーが別の要素をクリックしたときに何が起こるかは、互いに独立しており、バブリングによってリンクされることはありません。

8. それはいつも起こります

最初に理解する必要があるのは、イベントのキャプチャまたはバブリングが常に発生しているということです。ページドキュメント全体に対して一般的な onclick 処理関数を定義する場合


コードをコピーします コードは次のとおりです:
document.onclick = doSomething;
if (document.captureEvents) document.captureEvents(Event.CLICK);

ページ上の任意の要素をクリックするクリック イベントは、最終的にページの最上位のドキュメント レイヤーまでバブルアップし、前の処理関数がバブリングが終了しないことを明示的に指定しない限り、一般的な処理関数をトリガーします。ドキュメントレベル全体に伝播されます


上記のコードの 2 番目の文に追加:

>>> まず IE について話しましょう
object.setCapture() オブジェクトが setCapture されると、そのメソッドはキャプチャのためにドキュメント全体に継承されます。
ドキュメント全体をキャプチャするためにメソッドを継承する必要がない場合は、object.releaseCapture() を使用します
>>>その他
Mozilla にも同様の機能がありますが、メソッドは少し異なります
window.captureEvents (Event.eventType)
window.releaseEvents(Event.eventType)
>>>例

コードをコピー コードは次のとおりです:
//次の文だけがある場合、obj がクリックされたときのみクリックがトリガーされます obj.onclick = function(){alert(" something")}
//次の文を追加すると、メソッドはドキュメント (またはウィンドウ、ブラウザによって異なります) に継承され、
obj.captureEvents(Event.click); //FF
obj.setCapture() // IE

9. 使用方法

イベントの伝播はページドキュメント (このトップレベル) で終了するため、次のようなページがあると仮定すると、デフォルトのイベントハンドラーが可能になります。

コードをコピー コードは次のとおりです:

-------------------------- ---- --------
| 要素 1 |
| ----- |

----- --------------------------------- -
element1.onclick = doSomething;
element2.onclick = doSomething;
document.onclick =defaultFunction;


ユーザーが要素 1 または要素 2 をクリックすると、doSomething() が実行されます。イベントがdefaultFunction()にバブルアップしたくない場合は、必要に応じて、ここでイベントがバブルアップするのを防ぐことができます。ただし、ユーザーがページ上の別の場所をクリックした場合でも、defaultFunction() は実行されます。この効果は場合によっては役に立つかもしれません。

設定ページ - 処理機能でより大きなトリガー領域を設定できるようにします。これは「ドラッグ エフェクト」スクリプトで必要です。一般に、要素レイヤーでの Mousedown イベントの発生は、その要素が選択され、mousemove イベントに応答できるようになることを意味します。通常、マウスダウンはブラウザのバグを避けるためにこの要素レイヤーにバインドされますが、他の 2 つのイベント関数のスコープはページ全体 (?) でなければなりません

ブラウザ学の第一法則を思い出してください。何が起こってもおかしくありません。それが少なくともある程度の準備ができているときです。そこで何が起こるかというと、ユーザーがドラッグ&ドラッグするときにページ上でマウスを大きく動かしますが、スクリプトがその大きな振幅に応答できず、マウスが要素レイヤーに留まらなくなるということです

1. onmouseover ハンドラー関数が要素レイヤーにバインドされている場合、この要素レイヤーはマウスの動きに反応しなくなるため、ユーザーは違和感を感じます。

2. onmouseup ハンドラー関数が要素レイヤーにバインドされている場合の場合、イベントはトリガーされません。その結果、ユーザーがこの要素レイヤーをドロップしようとしても、要素レイヤーはマウスの動きに応答し続けます。これはさらなる混乱を引き起こすでしょう (?)


この例では、ハンドラー関数をページ レベルに配置することで常に確実に実行できるため、イベント バブリングは非常に便利です。

10. オフにします (イベントのバブルを防ぐため)

ただし、一般的には、各機能が相互に干渉しないように、すべてのバブリングとキャプチャをオフにする必要があります。さらに、ドキュメント構造が非常に複雑である場合 (多数のテーブルが相互にネストされているなど)、システム リソースを節約するためにバブリングをオフにすることもできます。この時点で、ブラウザはターゲット要素のすべての祖先をチェックして、ハンドラー関数があるかどうかを確認する必要があります。たとえ誰も見つからなかったとしても、先ほどの捜索にはまだ時間がかかります

Microsoft モデルでは、イベントの cancelBubble プロパティを true に設定する必要があります


コードをコピーします コードは次のとおりです以下:window.event.cancelBubble = true

w3c モデルでは、イベントの stopPropagation() メソッドを呼び出す必要があります
コードをコピーします コードは次のとおりです:
e.stopPropagation()

これにより、すべてのバブリングが外側に伝播するのを防ぎます。クロスブラウザーの解決策として、これを実行する必要があります:
コードをコピーします コードは次のとおりです:

関数 doSomething(e)

{
if (!e) var e = window.event;

e.cancelBubble = true;

if (e.stopPropagation) e.stopPropagation();

}

cancelBubble 属性をサポートするブラウザで cancelBubble を設定しても問題はありません。ブラウザは肩をすくめてこの属性を作成します。もちろん、これで実際にバブリングがキャンセルされるわけではありませんが、少なくともこのコマンドが安全で正しいものであることが保証されます

11. 現在のターゲット

前に見たように、イベントは target または srcElement 属性を使用して、イベントが発生したターゲット要素 (つまり、ユーザーが最初にクリックした要素) を示します。この場合、クリックしたのは要素 2 です。

キャプチャまたはバブリングフェーズ中のターゲット要素は変化せず、常に要素 2 に関連付けられていることを理解することが非常に重要です。

しかし、次の関数をバインドするとします。

コードをコピーします コードは次のとおりです:
element1。 onclick = doSomething;

element2.onclick = doSomething;


ユーザーが要素 2 をクリックすると、doSomething() が 2 回実行されます。しかし、どの HTML 要素がこのイベントに応答しているかをどうやって知るのでしょうか? target/srcElement も手がかりを与えませんが、イベントの原因である (ユーザーがクリックしたものであるため) 人々は常に要素 2 を好むでしょう。
この問題を解決するために、w3c は、イベントを処理している要素を指す currentTarget 属性を追加しました。これはまさに必要なものです。残念ながら、Microsoft モデルには同様の属性はありません
「this」キーワードを使用することもできます。上記の例では、currentTarget など、イベントを処理する HTML 要素に相当します。

12. Microsoft モデルの問題

しかし、Microsoft イベント バインディング モデルを使用する場合、this キーワードは HTML 要素と同等ではありません。 Lenovo には、currentTarget プロパティ (?) に似た Microsoft モデルがありません。上記のコードに従うと、次のことを意味します:

コードをコピー コードは次のとおりです:
element1.attachEvent('onclick',doSomething)

element2.attachEvent('onclick',doSomething)


どの HTML 要素がイベントの処理を担当しているのかを正確に知ることができません。これが Microsoft のイベント バインディング モデルの最も深刻な問題です。これは、Windows で IE 専用のアプリケーションを開発する場合でも、私が決して使用しない理由でもあります

currentTarget のようなプロパティをすぐに追加できるようにしたいと思っています。それとも標準に従うのでしょうか? Web 開発者にはこの情報が必要です

追記:

私は実際に JavaScript を使用したことがないため、この記事にはよく理解できない部分がいくつかあります。そのため、ドラッグ効果に関するセクションなど、追加または追加があれば、唐突に翻訳することしかできません。ご質問がありましたら、メッセージを残していただけますようお願いいたします。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート