7

次のような数百の「行」要素があります。

<div class='row'>
  <div class='cell'></div>
  <div class='cell'></div>
  <div class='cell'></div>
</div>

ページに既にレンダリングされた後、 clientHeight を取得する必要があります。「clientHeight」プロパティがリフローを強制することを知っています。これは、非常に多くのリフローがあるため、パフォーマンスが低下します。ただし、それらは既にレンダリングされており、レンダリングされてから高さを照会するまでの間、サイズが変わらないことがわかっています。

高さを照会するときにブラウザーにリフローしないように指示する方法はありますか? さらに、Webkitインスペクタは次のように述べています。

Layout tree size  5901
Layout scope      Whole document

そして、div は絶対配置された祖先内にあります。絶対配置された要素だけをリフローするべきではありませんか?

編集:

したがって、提供された答えは正しいです。このループがあったため、実際にはレイアウトを汚していました。

rows.each(function(){
  $(this).css('height', this.clientHeight);
});

コードをこれに変更すると、問題が修正されました。

var heights = rows.map(function(){
  return this.clientHeight;
});
rows.each(function(){
  $(this).css('height', heights.shift());
});
4

3 に答える 3

30

リフローは DOM が変更されるたびにキューに入れられますが、次のいずれかの場合にのみ実行されます。

  1. 処理する JavaScript がこれ以上ない (スクリプトの終わり) または

  2. など、レンダリングする必要がある計算値を照会する場合clientHeight

したがって、リフローを回避するには、次の規則に従う必要があります。

  • DOM を変更している間は DOM をクエリしないでください。

  • クエリを実行するときに DOM を変更しないでください

実際には、これは、DOM の変更を行った後、スクリプトの最後ですべてのクエリ操作をグループ化する必要があることを意味します。これを行うと、要素ごとに何千回もリフローするのではなく、何千もの要素に対して 1 回だけリフローします。

于 2013-11-06T15:29:01.510 に答える
6

clientHeight プロパティは、少なくともそれ自体ではリフローを強制しません。リフローをトリガーするには、次の 2 つが必要です。

  1. 現在のレイアウトをダーティにする (幅や高さなどのレイアウト プロパティを設定する)
  2. レイアウト プロパティのクエリ (clientHeight など)

幅または高さを設定する呼び出しを簡単にバッチ処理でき、JS コンテキストが制御を放棄するまでリフローは発生しません。レイアウト プロパティのクエリを簡単にバッチ処理でき、現在のレイアウトがダーティでない場合、リフローは発生しません。

1と2を続けて行うと問題が発生します。正確な情報でクエリを満たすために、リフローが強制されます。

私の知る限りでは、絶対配置された先祖を持つことで、リフローがドキュメント全体に「広がる」ことを制限する必要があることは正しいです(絶対配置先祖の親はリフローしません)。絶対配置された祖先内のすべてのアイテムは引き続きリフローします!

あなたの問題の解決策については、はいあります。次のようにキャッシュ メカニズムを設定します (疑似コード):

forEachDiv(function(div) {
  div.getClientHeight = function(){
    return div.cachedClientHeight = div.cachedClientHeight || div.clientHeight;
  }
});

その後、必要な回数div.getClientHeight()の代わりに使用でき、最初の使用のみがリフローをトリガーします (ダーティな場合)。div.clientHeight

明らかに、最初の提案に沿って、1 つのバッチ (= 1 つのリフロー) 内のすべての div に対して人為的に clientHeight をクエリすることもでき、その後は問題がなくなります。

// cache the client height for all divs now, to avoid reflows later
forEachDiv(function(div) {
  div.getClientHeight(); 
});
于 2013-11-06T15:33:36.437 に答える