I.はじめに
DOM 構造を変更するか、DOM 構造のスタイルを設定すると、リフローと再描画がトリガーされますが、異なるスタイルの変更がリフローと再描画をトリガーするかどうかは不明です。リフローと再描画については深く理解する必要があり、リフローを減らすことでパフォーマンスを向上させることができます。
ブラウザの解析とレンダリングのメカニズムを理解します。
(1). HTMLの解析、DOMツリーの生成、CSSの解析、CSSOMツリーの生成
(2). DOMツリーとCSSOMツリーを結合してレンダーツリー(Render Tree)を生成します。
(3). レイアウト(リフロー): 生成されたレンダリングツリーに従い、リフロー(レイアウト)を実行し、ノードの幾何学情報(位置、サイズ)を取得します。
(4).ペイント(再描画): レンダリングツリーとリフローで得られた幾何情報に従って、ノードの絶対ピクセルを取得します。
(5).Display: ピクセルを GPU に送信し、ページ上に表示します。
2. 転位(還流)
DOM の変更により要素の幾何情報(サイズ、位置)が変化した場合、ブラウザは要素の幾何情報(位置)を再計算してブラウザ上に正しく表示することを再配置、再描画ともいいます。
再配置はどのような状況で引き起こされるのでしょうか?
(1).表示される DOM 要素を追加または削除します(display:none;display:block)
(2).要素のサイズが変更されます(幅と高さ、外側の境界線のマージン、内側の境界線のパディング)
(3).要素の内容が変更されると、要素の幾何学的情報も変更されます。
(4).要素の位置(位置決めにより要素の位置を調整します)
(5).ページのレンダリングが開始されるとき
(6).ブラウザのウィンドウサイズが変わります
さらに、特定の値を取得すると、次のようにブラウザのリフローもトリガーされます。
offsetTop、offsetLeft、offsetWidth、offsetHeight、scrollTop、scrollLeft、scrollWidth、scrollHeight、clientTop、clientLeft、clientWidth、clientHeight、メソッドに加えて、getComputedStyle
原則は同じです
3. 再描画
要素の外観が変更されるが、要素の配置や分布には影響しない場合、一部の CSS スタイル、色、背景色、テキストの方向の変更、影の変更など、ブラウザが要素を再描画するプロセスを再描画と呼びます。
4. 再配置を減らすにはどうすればよいですか?
(1). 要素のスタイルを設定したい場合は、要素のクラス名を変更する(DOMツリーの最内層で可能な限り) (2). 複数のインラインスタイルを設定しないようにする (3).
適用
する要素のアニメーション、position 属性の固定値または絶対値を使用します (前の例で説明したように)
(4). テーブル レイアウトの使用は避けてください。テーブル内の各要素のサイズと内容により、テーブル全体が表示されます。 (5).複雑
なアニメーションの場合は、要素がドキュメント フローからできるだけ外れるように位置: 固定/絶対を設定し、他の要素への影響を軽減します (6). CSS3 ハードウェア アクセラレーションを使用すると、次のようなアニメーションが作成されます
。変換、不透明度、フィルタはリフロー再描画を引き起こさないため
(7) CSS を使用した JavaScript 式を避ける
例 1:要素のスタイルを変更したい場合、最初に display:none を使用して要素を非表示にし、ブラウザの再配置の回数を減らし、追加のパフォーマンスの消費を減らすことができます。
<div></div>
<script>
const div = document.querySelector('div');
// 先将元素隐藏
div.style.display = 'none';
div.style.width = '100px';
div.style.height = '100px';
div.style.border = '10px solid red';
div.style.background = 'red';
// 样式设置完毕
div.style.display = 'block';
</script>
例 2.複数のノードを動的に挿入すると、挿入された各ノードがブラウザーのリフローをトリガーします。DocumentFragment仮想ノードを使用すると、ブラウザーのリフローの回数を減らし、ブラウザーのパフォーマンスを確保できます。
<div></div>
<script>
const div = document.querySelector('div');
const fruits = ['Apple', 'Orange', 'Banana', 'Melon'];
// 创建了虚拟DOM节点
const fragment = document.createDocumentFragment();
fruits.forEach((fruit) => {
const li = document.createElement('li');
li.innerHTML = fruit;
fragment.appendChild(li);
});
// 一次性将节点插入到 DOM div的后面
div.appendChild(fragment);
</script>
演算結果
新しく追加された DOM 結果が div の後ろに追加されました
例 3:クラス名でスタイルを結合すると、リフローの回数を減らすこともできます。
スタイルをマージする前に、スタイルは js を通じて順次操作され、操作が実行されるたびにリフローまたは再描画を実行することができます
<div></div>
<script>
const div = document.querySelector('div');
// 先将元素隐藏
div.style.width = '100px';
div.style.height = '100px';
div.style.border = '10px solid red';
div.style.background = 'red';
// 样式设置完毕
</script>
スタイルを組み合わせる場合は、クラス名を操作してスタイルを設定します。たった 1 回の並べ替えと再描画で効果が得られます
<style>
.active {
width: 100px;
height: 100px;
background: red;
border: 10px solid red;
}
</style>
<div></div>
<script>
const div = document.querySelector('div');
div.style.background;
</script>
五、再配置と再描画の違い
リフローは、要素の幾何学的プロパティ、レイアウト情報、およびテキスト フローの再計算が必要なため、よりパフォーマンスを重視する操作です。再描画は、再描画のみが必要なため、比較的パフォーマンスを重視しない操作です。要素のスタイルは問題ありません。したがって、ページ上で頻繁な再配置操作を避けるようにしてください。複数の DOM 操作をバッチ処理することで再配置の回数を減らし、ページのパフォーマンスを向上させることができます。