JavaScript Eventは第8章イベントの順番を勉強します.

6719 ワード

基本的な問題は簡単です.あなたの要素が他の要素に含まれていると仮定します.
 
  
-----------------------------------
| element1 |
| ------------------------- |
| |element2 | |
| ------------------------- |

-----------------------------------
この二つの要素は全部Oclickイベント処理プログラムがあります.ユーザがelement 2の上をクリックすると、要素2と要素1の両方にクリックイベントがトリガされます.どの事件が先に発生しますか?どのイベントハンドラが先に実行されますか?つまり、イベントの順番は何ですか?
二つのモード
もちろん、Netscapeとマイクロソフトは過去の大変な日に自分の決定をしました.
Netscapeはelement 1が先に発生したと言います.これはイベントキャプチャーと言います.
マイクロソフトはelement 2が先に発生したと思います.これはイベントの泡といいます.
この二つの事件の順序はちょうど逆です.IEはイベントバーストのみをサポートします.Mozilla、Opera 7とKonquererの両方をサポートします.もっと前のOpearとiCabブラウザは両方ともサポートしていません.
イベントキャプチャ
あなたがイベントで捕獲した時
 
  

---------------| |-----------------
| element1 | | |
| --------- --| |----------- |
| |element2 \ / | |
| ------------------------- |
| Event CAPTURING |
-----------------------------------
element 1のイベントハンドラは先に実行し、element 2は後で実行します.
事件が勃発する
しかし、あなたが事件を使って泡が立った時
 
  
/ \
---------------| |-----------------
| element1 | | |
| ---------- -| |----------- |
| |element2 | | | |
| ------------------------- |
| Event BUBBLING |
-----------------------------------
element 2のイベントハンドラは先に実行します.element 1のイベントハンドラは後で実行します.
W 3 Cモード
W 3 Cはこの戦争で重力を維持することを決定しました.W 3 Cイベントモデルではどのイベントも最初にターゲット要素に到達するまで捕獲され、その後に泡が発生する.
 
  
| | / \
-----------------| |--| |-----------------
| element1 | | | | |
| ----------- --| |--| |----------- |
| |element2 \ / | | | |
| -------------------------------- |
| W3C event model |
------------------------------------------
デザイナーとして、イベントハンドラを捕獲するかそれとも発泡するかを選択してください.前の高級モードで紹介したaddEvent Listenerの方法で完成できます.最後のパラメータがtrueであればイベントキャプチャとして設定し、falseであればイベントの泡として設定します.
このように書いたら
element 1.addEvent Listener('click',doSomething 2,true)
element 2.addEvent Listener('click',doSomething,false)
ユーザーがelement 2をクリックすると次のようなことが発生します.
click事件は捕獲段階で発生した.このように見ると、element 2のいずれかの親要素がonclickイベントハンドラを持っている場合に実行されます.
イベントはelement 1でdoSomething 2を発見したら実行します.
イベントは目標そのものに転送されます.他のキャプチャ段階プログラムはありません.イベントは泡が発生する段階に入ってからdoSomething()、つまりelement 2は泡が発生する段階でイベントハンドラに登録されます.
イベントを再度上に転送し、父要素が発泡段階でイベントハンドラを設定しているかどうかを確認する.ここにはないので、何も起こりません.
逆:
element 1.addEvent Listener('click',doSomething 2,false)
element 2.addEvent Listener('click',doSomething,false)
現在ユーザーがelement 2の上をクリックすると発生します.
イベントclickは捕獲段階で発生する.イベントは、element 2の親要素がTrapフェーズにイベントハンドラに登録されているかどうかを調べます.ここにはありません.
目標そのものにイベントが下る.その後発泡段階を開始し、dosomething()を実行します.これはelement 2の発泡段階に登録されたイベントハンドラです.
イベントを引き続き上に転送し、父要素が発泡段階でイベントハンドラに登録されているかどうかを確認する.
イベントはelement 1を発見しました.そしてdoSomething 2()が実行されました.
従来モードの互換性
W 3 C DOMをサポートするブラウザにとって、従来のイベント登録
element 1.onclick=doSomething 2;
バブル期に登録されたとみられています.
イベント泡の使用
事件を意識して捕獲したり泡が立ったりするデザイナーは少ない.ホームページ制作の今日では、一連のイベントハンドラによって処理される必要はなさそうです.ユーザーもクリックした後に一連のイベントが発生して困惑することができて、通常あなたもあなたのイベントの処理のプログラムのコードに一定の独立性を維持したいです.ユーザーが要素をクリックすると、他の要素をクリックすると他のことが発生します.
もちろん将来的には変わるかもしれませんので、モデルを前向きに互換させた方がいいです.しかし、現在最も実用的なイベントの捕獲と発泡は、デフォルトの関数として登録されています.
それはいつも発生します
まず、あなたが理解する必要があるのは、イベントの捕獲や発泡がいつも発生していることです.もしあなたがあなたの全ページのためにonclickイベントを定義したら:
 
  
document.onclick = doSomething;
if (document.captureEvents) document.captureEvents(Event.CLICK);
任意の要素のclick時間にページに泡ができて、このイベントハンドラを出発しました.前のイベントハンドラが明確に泡を止めてこそ、ページ全体には伝わりません.
使用
すべてのイベントがドキュメント全体で停止されるため、デフォルトのイベントハンドラが可能になります.このようなページがあるとします.
 
  
------------------------------------
| document |
| --------------- ------------ |
| | element1 | | element2 | |
| --------------- ------------ |

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

element1.onclick = doSomething;
element2.onclick = doSomething;
document.onclick = defaultFunction;
現在ユーザーがelement 1またはelement 2をクリックするとdoSomething()が実行されます.これで彼の伝播を阻止することができます.そうでなければdefaultFunctionが実行されます.ユーザーの他の場所でのクリックもdefaultFunction()に実行させます.これは時々役に立ちます.
グローバルのイベントハンドラを設定するには、ドラッグコードを書く際に必要です.通常のレイヤー上のmousedowイベントは、このレイヤーを選択してmousemoveイベントに応答します.mousedownは通常この階に登録してブラウザのbugを避けますが、他のイベントハンドラはすべてグローバルでなければなりません.
ブラウザのロジックの第一法則を覚えてください.何でも起こるし、常にあなたの準備が一番少ない時です.ユーザのマウスが狂ったように移動し、コードが追いついていないため、マウスがもうこのレイヤーにいなくなりました.
あるレイヤーにオンラインイベントハンドラを登録したら、このレイヤーがマウスの動きに応答しなくなったら、ユーザーを混乱させます.
もしあるものがオンラインイベントハンドラに登録されていたら、プログラムはユーザーがマウスを離す時にプログラムが捉えられなくなります.このレイヤーはまだマウスに従って移動しています.
この場合には、イベントの泡が発生することが重要です.全体的なイベントハンドラは必ず実行します.
消します
しかし、通常は関連の捕獲と発泡をすべてシャットダウンしたいです.また、もしあなたのドキュメント構造が非常に複雑であれば(例えば、複雑なテーブルの山のような)システムリソースを節約するために発泡スチロールをオフにする必要があります.さもなくばブラウザは一つ一つの親要素がイベントハンドラがあるかどうかを確認します.一つもないかもしれませんが、探すのと同じように時間がかかります.
マイクロソフトモードではイベントのキャンセルBbble属性をtrueに設定してください.
window.event.cnce Bubble=true
W 3 Cモードでは、stopPropagation()を呼び出す必要があります.
e.stopPropagation()
これはこの事件の泡立ち段階を阻止する.事件の捕獲を阻止することは基本的に不可能である.なぜか知りたいです.
完全なクロスブラウザのコードは以下の通りです.
 
  
function doSomething(e)
{
if (!e) var e = window.event;
e.cancelBubble = true;
if (e.stopPropagation) e.stopPropagation();
}
cancel Bbbleがサポートされていないブラウザに設置しても大丈夫です.ブラウザはこのような属性を作成します.もちろん無駄です.安全のためだけに.
currentTarget
前に話したことがありますが、一つの事件にはtargetまたはsrcellmentが含まれています.一つの事件の要素の引用が含まれています.私たちの例ではelement 2はユーザーが彼をクリックしたからです.
捕獲と泡発生の間にこのtargetは変わらないことを理解することが重要である.彼は常にelement 2を指す.
しかし、下記のイベントハンドラを登録したと仮定します.
element 1.onclick=doSomething;
element 2.onclick=doSomething;
ユーザーがelement 2をクリックすると、doSomethingは2回実行されます.どのようにしてそのHTML元素がこの事件を処理しているかを知りますか?target/scrElementも答えを出すことができなくて、事件の初めからずっとelement 2を指しています.
この問題を解決するために、currentTarget属性を追加しました.それは処理中のイベントのHTML要素の参照を含みます.残念なことに、マイクロソフトモデルには似たような属性がありません.
あなたもthisキーワードを使ってもいいです.この例では、処理中のイベントを指すHTML要素は、まずcurrentTargetである.
マイクロソフトモードの問題
しかし、マイクロソフトのイベント登録モデルを使用すると、HTMLの要素だけを考えているわけではない.そして、currentTargetのような属性がないということは、もしそうすれば、
element 1.atachEvent('onclick',doSomething)
element 2.atachEvent('onclick',doSomething)
あなたはそのHTML元素が事件を処理していることを知らないです.これはマイクロソフトのイベント登録モードの一番深刻な問題ですので、彼を使わないでください.たとえIE/winの下のプログラムであっても.
私はマイクロソフトがcurrentTargetのような属性を早く追加してほしいです.あるいは標準に従いますか?私たちは設計が必要です.
続行
勉強を続けたいなら、次の章を見てください.
原文の住所:http://www.quirksmode.org/js/events_order.
私のtwitter:@rehawk