web-dev-qa-db-ja.com

無限スクロールまたは多数のdom要素を使用したパフォーマンス?

多数のdom elmenetsとパフォーマンスについて質問があります。

ページに6000個のdom要素があり、ユーザーがTwitterなどのページ(ユーザーがスクロールして新しいdom要素を作成する)を操作すると、要素の数を増やすことができます。

ページのパフォーマンスを改善するために、2つのことしか考えられません。

  1. リフローを回避するために、非表示アイテムの表示をnoneに設定します
  2. 見えないアイテムをdomから削除し、必要に応じて再度追加します。

多くのDOM要素を含むページを改善する他の方法はありますか?

67
Moon

これを自分で体験することはできませんが、いくつかの素晴らしいヒントがあります: http://engineering.linkedin.com/linkedin-ipad-5-techniques-smooth-infinite-scrolling-html5

私はFacebookを見たが、彼らはFirefoxでは特に何もしないようだ。下にスクロールしても、ページ上部のDOM要素は変わりません。 Facebookがさらにスクロールすることを許可しないうちに、Firefoxのメモリ使用量は約500メガに上昇します。

TwitterはFacebookと同じように見えます。

Googleマップは別の話です-見えないマップタイルはDOMから削除されます(すぐにではありませんが)。

24
cbp

FoldingText で同様の問題に対処する必要がありました。ドキュメントが大きくなるにつれて、より多くのライン要素と関連するスパン要素が作成されました。ブラウザーエンジンが詰まるように見えたため、より良いソリューションを見つける必要がありました。

これが私たちがしたこと、あなたの目的に役立つかもしれないし、役に立たないかもしれません:

ページ全体を長いドキュメントとして視覚化し、ブラウザのビューポートを長いドキュメントの特定の部分のレンズとして視覚化します。あなたは本当にレンズ内の一部を表示する必要があります。

したがって、最初の部分は、表示可能なビューポートを計算することです。 (これは、要素の配置方法、絶対/固定/デフォルトに依存します)

var top = document.scrollTop;
var width = window.innerWidth;
var height = window.innerHeight;

より多くのブラウザベースのビューポートを見つけるためのいくつかのリソース:

JavaScriptでブラウザのビューポートの寸法を取得

ブラウザウィンドウのscrollTopを検出するためのクロスブラウザメソッド

次に、その領域にどの要素が表示されるかを知るためのデータ構造が必要です

すでにテキスト編集用のバランスの取れたバイナリ検索ツリーが用意されていたので、行の高さを管理するために拡張したため、この部分は比較的簡単でした。要素の高さを管理するために複雑なデータ構造が必要になるとは思わない。単純な配列またはオブジェクトで問題ない場合があります。簡単に高さと寸法を照会できることを確認してください。さて、どのようにしてすべての要素の高さデータを取得しますか。非常に単純です(ただし、大量の要素の場合は計算コストがかかります!)

var boundingRect = element.getBoundingClientRect()

私は純粋なJavaScriptの観点から話をしていますが、jQueryを使用している場合は$.offset$.position、およびリストされているメソッド here は非常に役立ちます。

繰り返しますが、データ構造の使用はキャッシュとしてのみ重要ですが、必要に応じて、オンザフライで実行できます(ただし、これらの操作はコストがかかると述べています)。また、CSSスタイルを変更し、これらのメソッドを呼び出すことに注意してください。これらの関数は再描画を強制するため、パフォーマンスの問題が発生します。

最後に、オフスクリーンの要素を単一の<div>計算された高さの要素

  • これで、データ構造に格納されているすべての要素の高さがあり、表示されているビューポートの前にあるすべての要素を照会します。

  • <div>要素の高さの合計にCSSの高さ(ピクセル単位)を設定して

  • フィラーdivがわかるように、クラス名でマークします
  • このdivがカバーするdomからすべての要素を削除します
  • 代わりに、この新しく作成されたdivを挿入します

表示されているビューポートの後にあるの要素について繰り返します。

スクロールを探し、イベントのサイズを変更します。各スクロールで、データ構造に戻り、フィラーdivを削除し、以前に画面から削除された要素を作成し、それに応じて新しいフィラーdivを追加する必要があります。

:)長くて複雑な方法ですが、大きなドキュメントの場合はパフォーマンスが大幅に向上しました。

tl; dr

適切に説明したかどうかはわかりませんが、この方法の要点は次のとおりです。

  • 要素の垂直方向の寸法を知る
  • スクロールされたビューポートを知る
  • すべてのオフスクリーン要素を単一のdivで表します(高さは、それがカバーするすべての要素の高さの合計に等しい)
  • 常に2つのdivが必要になります。1つは表示ビューポートの上にある要素用、もう1つは下にある要素用です。
  • スクロールおよびサイズ変更イベントをリッスンして、ビューポートを追跡します。それに応じてdivと可視要素を再作成します

お役に立てれば。

95
Mutahhir

それは2019年です。質問は本当に古いですが、私たちは今もReact JS。

Facebookのタイムラインは、display: none !importantクラスターが表示されなくなるとすぐに、DOMの以前にレンダリングされたすべての要素がDOMに保持されます。表示されないものはdisplay: none !important。また、非表示クラスターの全体の高さは、非表示クラスターの親divに設定されます。

ここに私が作ったスクリーンショットがあります:

enter image description here

enter image description here

enter image description here

2019年現在、このアプローチについてどう思いますか?また、Reactを使用する人にとって、Reactでどのように実装できますか?このトリッキーなトピックに関するご意見やご感想をいただければ幸いです。

ご清聴ありがとうございました!

1
tonix