46

次の Web ページを考えてみましょう。

 <html>
   <body onscroll="alert('body scroll event')">
     <div style='width:200px;height:200px;overflow:auto' onscroll="alert('div scroll event')">
       <div style='height:400px'>
       </div>
     </div>
   </body>
 </html>

この html は、スクロールバーを持つ div を作成します。スクロールバーを動かすとonscroll、div 要素のイベントがトリガーされます。ただし、onscroll本体のイベントは発生しません。onscrollW3C は要素イベントが「バブル」しないと述べているため、これは予期されたものです。

ただし、ページの任意の要素のスクロールバーがスクロールされるたびに知る必要があるクライアント側の Web フレームワークを開発しています。これは泡があれば簡単にできますonscrollが、残念ながらそうではありません。onscrollページ全体でイベントを検出する他の方法はありますか? (今は主に Webkit に集中しているので、Webkit 固有のソリューションで問題ありません...)

ここに私が試したいくつかのことがあります:

  1. キャプチャDOMAttrModified(スクロールバーの移動では起動しないようです。)
  2. DOM オブザーバーの使用 (スクロールバーに対しても起動しないようです)
  3. イベントの種類をバブルに変更onscroll(できないらしい)

onscrollイベントをグローバルにキャプチャする唯一の方法はonscroll、スクロールする可能性のあるすべての要素にイベントをアタッチすることです。これは非常に見苦しく、フレームワークのパフォーマンスを損なうことになります。

誰もがより良い方法を知っていますか?

4

5 に答える 5

99

最新のブラウザですべてのスクロール イベントを検出する最も簡単な方法は、イベントをアタッチするときに「バブリング」ではなく「キャプチャ」を使用することです。

window.addEventListener('scroll', function(){ code goes here }, true)

残念ながら、私が認識しているように、<= IE8 などの古いブラウザには同等のものはありません

于 2015-10-05T17:37:28.203 に答える
13

これと同じ問題がありました。

もちろん、最も簡単な方法は jQuery を使用することです。この方法を使用すると、ページが大幅に遅くなる可能性があることに注意してください。また、イベントがバインドされた後に追加される新しい要素は考慮されません。

$("*").scroll(function(e) {
    // Handle scroll event
});

バニラ JavaScript では、呼び出し時にuseCaptureブール値を設定でき、動的に追加された要素を含むすべての要素で起動します。trueaddEventListener

document.addEventListener('scroll', function(e) {
    // Handle scroll event
}, true);

ただし、これはスクロール イベントが実際に発生する前に発生することに注意してください。私が理解しているように、イベントには 2 つの段階があります。キャプチャ フェーズが最初に発生し、ページ ルート (ownerDocument?) から開始し、イベントが発生した要素までたどります。この後、要素からルートに戻るバブリング フェーズが続きます。

いくつかの簡単なテストでも、これが jQuery の処理方法である可能性があることが示されました (少なくともすべてのページ要素のスクロールを追跡するため) が、100% 確実ではありません。

これは、バニラ JavaScript メソッドを示す JSFiddle ですhttp://jsfiddle.net/0qpq8pcf/

于 2015-03-03T14:56:36.060 に答える
9

* ...コオロギのさえずり... *

わかりました、この質問はスタックオーバーフローの愛を得るつもりはないので、別のユーザーがこの質問に出くわした場合に備えて、これまでに見つけた最良の解決策について自分の質問に答えたほうがよいでしょう:

私が思いついた最善の解決策は、BODY 要素の「onmousedown」と「onkeydown」をキャプチャすることです。これらのイベントはバブリングするため、ユーザーがページ上のスクロールバーを動かそうとすると、これらのグローバル関数が by-製品。次に、これらの関数で event.target を検索し、マウス/キーが再び「上」になるまで一時的な「onscroll」イベントをこれらのオブジェクトにアタッチします。この方法を使用すると、「ハンドラーの肥大化」を回避しながら、すべての「onscroll」イベントをグローバルにキャプチャできます。(これは「マウスホイール」スクロールでも機能すると思いますが、最終的なしわに関する私の研究はまだ保留中です。)

于 2012-11-02T15:04:40.033 に答える