【転】JavaScript事件手順:発泡と捕獲

7343 ワード

補足説明:この文章は簡単に泡が出て、捕獲原理を説明しました.原文はppk侠客のquirksmoodeサイトから来ました.ネット友達hh 54188の翻訳に感謝します.
イベントの発生順
この問題の起源は非常に簡単で、もしあなたがもう一つの要素の中に他の要素を入れ込んでいると仮定します.
-----------------------------------
| element1                        |
|   -------------------------     |
|   |element2               |     |
|   -------------------------     |
|                                 |
-----------------------------------
そしてどちらもワンクレックイベントハンドリングのハンドルがあります.ユーザーが要素2をクリックすると、要素1と要素2のクリックイベントがトリガされます.しかし、どのイベントが先にトリガされますか?どのイベント処理関数が先に実行されますか?つまり、事件の発生順はどうなりますか?
二つのモデル
案の定、「振り返るに忍びない」(ブラウザ大戦)の日には、Netscapeとマイクロソフトの2つの異なる処理方法があります.
  • Netscapeは、要素1のイベントが最初に発生すると主張しています.このようなイベントの発生順序は、捕獲型
  • と呼ばれています.
  • マイクロソフトは元素2を保持して優先権を持っています.このような事件の順序はバブル型
  • と呼ばれています.
    この二つの事件の順序ははっきりと反対である.Explorerブラウザは、発泡事象のみをサポートしています.Mozila、Opera 7、Konquerer両方ともサポートしています.もっと古いoperaとiCabは両方とも支持していません.
    捕獲型イベント
    捕獲型イベントを使用すると
                   | |
    ---------------| |-----------------
    | element1     | |                |
    |   -----------| |-----------     |
    |   |element2  \ /          |     |
    |   -------------------------     |
    |        Event CAPTURING          |
    -----------------------------------
    
    要素1のイベントハンドラ関数は、最初にトリガされ、要素2のイベントハンドラ関数は最後にトリガされる.
    バブル型事件
    バブル型のイベントを使う時
                   / \
    ---------------| |-----------------
    | element1     | |                |
    |   -----------| |-----------     |
    |   |element2  | |          |     |
    |   -------------------------     |
    |        Event BUBBLING           |
    -----------------------------------
    
    要素2の処理関数は、最初にトリガされ、要素1の次に
    W 3 Cモデル
    W 3 cは賢明にもこの争いの中で選択された方案です.w 3 cイベントモデルで発生したイベントのうち、最初はターゲット要素に到達するまで捕獲段階に進み、更に発泡段階に入る.
                     | |  / \
    -----------------| |--| |-----------------
    | element1       | |  | |                |
    |   -------------| |--| |-----------     |
    |   |element2    \ /  | |          |     |
    |   --------------------------------     |
    |        W3C event model                 |
    ------------------------------------------
    
    ウェブ開発者のために、捕獲段階であるかそれとも発泡段階であるかを選択することができます.これはaddEventListener()法によって実現されます.この関数の最後のパラメータがtrueであれば、捕獲段階でのバインディング関数、逆false、発泡段階でのバインディング関数です.
    あなたが作るなら
    element1.addEventListener('click',doSomething2,true)
    
    element2.addEventListener('click',doSomething,false)
    
    ユーザーが要素2をクリックすると、次のようになります.
    (事件はここでは観光客のように、外から内へ観光して、触発された主要な要素に近づいてきて、また逆に離れていく)
  • は、イベントをクリックして最初に獲得段階に入ります.要素2の祖先要素のうち、捕獲段階においてonclick処理関数があるかどうかを確認する
  • .
  • は、要素1があることを発見し、doSomething 2が実行される
  • .
  • イベントはターゲット自身(要素2)をチェックしました.捕獲段階ではより多くの処理関数が発見されませんでした.イベントは発泡段階に入り始め、当然ながらドソメット()を実行したいと思います.これは元素2の発泡段階の関数に結び付けられています.
  • イベントは、発泡段階でどのような祖先要素が一つの処理関数に結合されているかを確認するために、要素2から遠い方向に向かっている.このような状況がないので、何も起きていません.
    反対の場合は、
    element1.addEventListener('click',doSomething2,false)
    element2.addEventListener('click',doSomething,false)
    
    今ユーザーが要素2をクリックすると発生します.
  • イベントをクリックしてキャプチャフェーズに入ります.要素2の祖先元素の中に、捕獲段階でのOclick処理関数があるかどうかを確認したところ、結果は全く得られなかった.
  • 事件は目標自分を検査しました.イベントは発泡段階に入り始め,要素2の発泡相に結合された関数を実行した.doSomething()
  • イベントはターゲットから離れ始め、要素2の祖先要素の中に処理関数を結合したものがあるかどうかを確認する
  • .
  • に1つが発見され、要素1のドソメンテーション2が実行される.
    互換性と伝統モデル
    w 3 c dom(ドキュメントオブジェクトモデル)をサポートするブラウザで、従来のイベントバインディング方法は
    element1.onclick = doSomething2;
    
    デフォルトは、発泡段階にバインディングされていると見なされます.
    バブル型のイベントを使う
    まれな開発者は、バブル型のイベントや捕獲型のイベントを意識的に使う.彼らが今日作ったウェブページの中で、一つの事件を泡のためにいくつかの関数で処理する必要がない.しかし、ユーザーは通常、彼らがマウスを1回クリックしただけで、多くの場合(複数の関数が実行され、泡が発生するため)が発生してしまうので、疑問に思うことがあります.多くの場合、あなたはやはりあなたの処理関数が独立してほしいです.ユーザーがある元素をクリックしたら、何が起きますか?他の元素をクリックして、何が発生しますか?
    ずっと起きています
    まず第一に、事件の捕獲や泡が発生していることを理解してください.ページ全体の定義を与えると、汎用的なOclick処理関数があります.
    document.onclick = doSomething;
    if (document.captureEvents) document.captureEvents(Event.CLICK);
    
    ページ上で任意の要素のクリックイベントをクリックすると、最終的にページの一番上の文書層に泡ができます.したがって、その汎用的な処理関数をトリガします.前の処理関数で明確に指摘されていない限り、発泡はドキュメント全体に広がりません.
    使い方(この細かいところの翻訳はよくないです.実戦がないので、私もよく分かりません.メッセージの中で補充できます.更新します.)
    どのイベントの伝播もページドキュメント(この最上位層)で終了しますので、デフォルトのイベントハンドラが可能になります.このようなページがあると仮定してください.
    ------------------------------------
    | document                         |
    |   ---------------  ------------  |
    |   | element1    |  | element2 |  |
    |   ---------------  ------------  |
    |                                  |
    ------------------------------------
    element1.onclick = doSomething;
    element2.onclick = doSomething;
    document.onclick = defaultFunction;
    
    現在、ユーザーが要素1または要素2をクリックすると、ドソmething()が実行されます.もしあなたが望むなら、イベントをdefaultFunctionに泡を作りたくないなら、ここでイベントの泡が上に広がるのを止めることができます.しかし、ユーザーがページ上の他の部分をクリックすると、defaultFunction()が実行されます.このような効果は時には使えるかもしれません.
    ページの設定­——処理関数を広範囲のトリガ面積にするには、「ドラッグ効果」スクリプトで必要です.一般的には、ある要素層でmousedownイベントが起こるということは、この要素が選択され、mousemooveイベントに応答できるようにすることを意味する.mousedownは通常、ブラウザのbugを回避するためにこの要素層に結びつけられているが、他の2つのイベント関数の範囲はページ全体でなければならない(?)
    ブラウザ学の第一法則(First Law of Browserology)を覚えてください.すべてが可能です.そして、少なくとも準備ができている時です.そのため、ユーザーがドラッグした時、大幅にページ上で彼のマウスを移動しましたが、スクリプトは大幅に反応できず、マウスも元素層に留まらなくなりました.
  • onmouseover処理関数が要素層に結合されている場合、この元素層はマウスの移動に対して何の反応も示さないので、ユーザーに変な感じを与えます.
  • もしonmouseup処理関数が要素層に結び付けられていたら、イベントもトリガされず、結果として、ユーザーがこの元素層を下に置いた後、元素層はマウス移動に反応し続けます.これはより多くの迷いを引き起こすことができる(?)
  • .
    したがって、この例では、イベントの泡が非常に効果的です.あなたの処理関数をページ層に置いて、彼らが常に実行されることを保証できます.
    それを消してください
    しかし、一般的には、関数間の邪魔にならないように、すべての泡を切って捕獲したいと思います.これ以外にも、かなり複雑な構造の文書(多くのテーブル同士が入れ子になっているか、あるいはこれらのような)があれば、システムリソースを節約するために、泡が出てきます.この時、ブラウザはターゲット要素の各祖先を確認し、処理関数があるかどうかを確認しなければなりません.一つも見つからなかったとしても、先ほどの検索には時間がかかります.
    マイクロソフトのモデルでは、イベントのcancel Bubble属性をtrueに設定しなければなりません.
    window.event.cancelBubble = 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 Bubble属性をサポートするブラウザにcancel Bubbleを設置するのは大層な問題がありません.ブラウザは肩をすくめてこの属性を作成します.もちろんこれは本格的に泡をキャンセルすることはできませんが、少なくともこのコマンドは安全で正しいです.
    currentTarget
    私たちが前に見たように、一つのイベントはtargetまたはsrcellement属性を用いて、イベントがどのターゲット要素(即ちユーザが最初にクリックした要素)にあるかを表します.私たちの例では元素2です.クリックしたからです.
    非常に重要なことは、捕獲または発泡段階におけるターゲット要素は不変であり、常に要素2に関連していることを理解することである.
    以下の関数を紐付けたと仮定します.
    element1.onclick = doSomething;
    element2.onclick = doSomething;
    
    ユーザーが要素2をクリックすると、doSomething()が2回実行されます.しかし、どのhtml元素がこの事件に応答しているかどうやって分かりますか?target/srcellementも手がかりを与えていませんが、人々はいつも要素2に傾いています.これはイベントを引き起こす原因です.
    この問題を解決するために、w 3 cはcurrentTargetという属性を増加させ、イベントを処理している要素を指す.残念ながら、マイクロソフトのモデルには似たような属性がありません.
    あなたも「this」というキーワードを使ってもいいです.上記の例では、事件を処理しているhtml要素に相当し、まるでcurrentTargetのようです.
    マイクロソフトモデルの問題
    しかし、マイクロソフトのイベントバインディングモデルを使用すると、thisのキーワードはHTMLの要素に相当しません.連想にはcurrentTargetのようなマイクロソフトモデルが欠けています.上のコードで操作すれば、あなたがそうするという意味です.
    element1.attachEvent('onclick',doSomething)
    element2.attachEvent('onclick',doSomething)
    
    どのHTML元素が事件を処理しているかを正確に知ることができません.これはマイクロソフトのイベントバインディングモデルの一番深刻な問題です.私にとって、これもWindowsの下でIEだけのアプリケーションを開発しているからです.
    できるだけ早くcurrentTargetの類似の属性を増加したいです.あるいは標準に従いますか?ウェブ開発者にはこれらの情報が必要です.
    来源:qingbob
    転載先:https://www.cnblogs.com/snowinmay/p/3230017.html