lxyuma BLOG

開発関係のメモ

jQueryでのuseCaptureの扱い(addEventListenerの引数)

今、javascriptの勉強会用の資料を書いているのだが。

target.addEventListener(type, listener [, useCapture]);

のuseCaptureについて、

jQuery内でどう使われているか調べてみたら、

面白かったので、そのまとめ。

useCaptureとは?

addEventListenerを書く時の3番目のbooleanの引数。

ただ、この説明だと、よくわからない。

この説明が一番、分かり易かった。

要するに、

  • useCapture=false : 通常のイベントハンドラ

    • バブリングフェーズで呼ばれる
    • DOMの子から親にイベントが伝搬する
  • useCapture=trueのイベントハンドラ

    • キャプチャフェーズで呼ばれる
    • DOMの親から子にイベントが伝搬する

実際の所

  • useCapture=falseのままで良さそう。

    • ブラウザ毎の動作違いを防ぐため(特にIE)

IEとuseCapture

  • IE9から

    • addEventListenerに対応
  • IE8まで

    • attachEventを使わないといけない。

      • キャプチャフェーズが無いっぽい(useCaptureが設定できない)

なので、useCapture=trueでIE以外のbrowserで動いても、

IE8以下で、異なる動作をしてしまう可能性がある。なので、false。

jQueryでどうなってるのか?

ここからが本題。

jQueryでどう扱われているのか、気になった。

jQuery本体をgit cloneして、grepした

jqueryでaddEventListenerをgrep

$ find src/ -type f -print | xargs grep addEventListener --color=auto
src//core.js:           document.addEventListener( "DOMContentLoaded", completed, false );
src//core.js:           window.addEventListener( "load", completed, false );
src//event.js:              // Only use addEventListener if the special events handler returns false
src//event.js:                  if ( elem.addEventListener ) {
src//event.js:                      elem.addEventListener( type, eventHandle, false );
src//event.js:                  document.addEventListener( orig, handler, true );

結論

  • 殆ど、useCapture=false固定だった。(バブリングフェーズ)

  • 例外的に、最後の1行だけ、useCapture=trueを固定で設定している箇所があった。

これは?

jQueryでuseCapture=true

// Create "bubbling" focus and blur events
// Support: Firefox, Chrome, Safari
if ( !jQuery.support.focusinBubbles ) {
    jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {

        // Attach a single capturing handler while someone wants focusin/focusout
        var attaches = 0,
            handler = function( event ) {
                jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
            };

        jQuery.event.special[ fix ] = {
            setup: function() {
                if ( attaches++ === 0 ) {
                    document.addEventListener( orig, handler, true );
                }
            },
            teardown: function() {
                if ( --attaches === 0 ) {
                    document.removeEventListener( orig, handler, true );
                }
            }
        };
    });
}

この固まりの、真ん中で、

  • addEventListenerの第3引数(useCapture)が 「 true 」になっている。

focus / blurの時だけ、useCapture=trueにしてる?

focus blurイベントとjQuery

この標準的な動きに合わせるために、

useCapture=trueにしているっぽい。

その他のイベントは?

上記のDOMのpage見ると、他にもbubbling:noと書いているイベントが2つある。

  • load
  • unload

これらは、多分、バブリングで困る事は無いから

(focusみたいにDOM触らないから)

わざわざ書いてないのかな?

IE8とjquery

確認していないけど、IE8だと、focusの動きが若干違うという事かな?

そもそも、IE8は、今のjquery2から捨てられてるしね。

おしまい。