Passive Event Listenersのミニマムpolyfillを書いた。

  • 5
    いいね
  • 0
    コメント

Passive Event Listenersとは?

addEventListenerの第三引数に指定できる新しいオプションです。
https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md

こんな感じで使います。

window.addEventListener('scroll', function(){...}, {passive: true});

簡単に言うと、scrollイベントの発生時にpreventDefault()が呼ばれるかどうかの確認をスキップし、scrollイベントの効率化を図るものです。

存在を知ったのは半年くらい前で、その時は知識として留めていたのですが、そろそろ実務で実験的に使いたいと思い、最低限のpolyfillを作って実装を入れ込みました。入れようと思った理由は、モダンブラウザの対応が進んできたからですね。
http://caniuse.com/#search=passive

※Safariの10以上、iOS Safariの10.2以上でサポートされているのはなかなか大きいと思います。

どうしてpolyfillが必要?

冒頭のサンプルコードを思い返してください。

window.addEventListener('scroll', function(){...}, {passive: true});

第三引数にpassive:trueを指定しているのですが、このオプションがサポートされていないブラウザでは空のオブジェクトだと見なされます。
JavaScriptでは空のオブジェクトはtrue扱いになるので、IEやEdge(2017/02/28時点で最新のEdge)では以下の記述と同様の判断をされてしまいます。

window.addEventListener('scroll', function(){...}, true);

第三引数のuseCaptureが意図せずtrueになるのは避けたいため、addEventListener時にブラウザ実装有無を確かめる必要があるわけです。

今回書いたpolyfill

function isSupportPassive(){
  if (typeof window === 'object' && typeof window.addEventListener === 'function' && Object.defineProperty) {
    let passive = false;
    const options = Object.defineProperty({}, 'passive', {
      get() { passive = true; }
    });
    window.addEventListener('test', null, options);
    return passive;
  }
}

// how to use
window.addEventListener('scroll', function(){...}, isPassiveSupport() ? {passive: true} : false);

最低限の実装ですが、これで処理分けを実現できます。

codepenでデモも作ったので、興味の有る方がお試しを。

まとめ

  • lazyload
  • 要素をスクロール途中から追従させる

この辺の処理をやっている箇所には入れてあげるといいかもしれません。
二つ目の「途中から追従」に関しては、position:stickyという解決策もあるので、後々もっと楽に実装できるようになると思います。