Dom ノードを最適化する方法

醉折花枝作酒筹
リリース: 2021-04-12 11:16:39
オリジナル
2491 人が閲覧しました

この記事では、Dom ノードの最適化計画を紹介します。一定の参考値があるので、困っている友達が参考になれば幸いです。

Dom ノードを最適化する方法

DOM 操作は、ブラウザーの再描画とリフローにつながるため、パフォーマンスに最も大きな影響を与えます。ページ UI への変更が DOM 操作を通じて行われることは誰もが知っています。DOM は多数ありますが、 DOM の操作を容易にするために API が提供されていますが、DOM 操作のコストは非常に高く、ページのフロントエンド コードのパフォーマンスのボトルネックのほとんどは DOM 操作に集中しています。したがって、フロントエンドのパフォーマンスの最適化の主な焦点は、 DOM 操作の最適化です。

ブラウザ レンダリング メカニズム:

Dom ノードを最適化する方法
ブラウザはページをレンダリングします。
Dom ノードを最適化する方法

  1. ブラウザは HTML ドキュメントのソース コードを解析し、次に、DOM ツリーを構築し、スタイルが見つかったときにそれを非同期的に計算します。

  2. 非同期的に計算されたスタイルは、DOM ツリーと合成されて、レンダー ツリーが構築されます。

  3. レンダー ツリーをレイアウトします。

  4. レンダー ツリーを描画します。

DOM ツリーとレンダー ツリーの違いは、display:none; スタイルを持つノードは DOM ツリーには存在しますが、レンダー ツリーには存在しないことです。ブラウザーはそれを描画した後、js ファイルの解析を開始し、js に基づいて再描画およびリフローするかどうかを決定します。

リフロー・再描画

ページ変更が発生したときに発生する操作:

  1. リフロー: ブラウザ エンジンは、レンダー ツリー内の特定のノードが変更されたことを検出し、影響を及ぼします。レイアウトに戻って再レンダリングする必要があるため、このロールバック プロセスをリフローと呼びます。リフローはこのルート フレームから下方向に再帰的に行われ、すべてのノードの幾何学的寸法と位置が順番に計算されます。
  2. 再描画: ページの DOM レイアウトに影響を与えることなく、要素の背景色、テキスト色、境界線の色などを変更します。

js はシングルスレッドであるため、再描画とリフローはユーザーの操作をブロックし、Web ページのパフォーマンスに影響します

最適化: リフローの再描画の数を削減します

1、複数の dom スタイルを変更し、スタイルの代わりにクラスを使用して、リフローと再描画の複数のトリガーを削減します
例: dom 要素の幅と高さを変更します

var dom = document.getElementById('box')
dom.style.width = '300px'
dom.style.height = '300px'//访问了三次dom,触发了两次回流和两次重绘
ログイン後にコピー

最適化後:

.change {
    width: 300px;
    height: 300px;
    }
    document.getElementById('p').className = 'change'//只触发一次
ログイン後にコピー

2. リスト タイプをバッチで変更し、ドキュメント フローから切り離して復元します。display:none; スタイルを持つノードは DOM ツリーには存在しますが、レンダリング ツリーには存在せず、再描画リフローは発生しません。 。

DOM コレクション内の各 DOM 子ノードにクラスを追加する場合は、各ノードをトラバースしてクラスを追加することで、複数の再描画とリフローをトリガーできます。 #3. DocumentFragment


Virtual DOM は実際にはオブジェクトです. js は空の仮想ノード オブジェクトを作成するための reateDocumentFragment() メソッドを提供します. DocumentFragment ノードはドキュメント ツリーに属しません. 複数の DOM 要素がある場合を追加する必要がある場合、これらの要素を最初に DocumentFragment に追加し、次に DocumentFragment オブジェクトをレンダリング ツリーに追加すると、ページが DOM をレンダリングする回数が減り、効率が大幅に向上します。

/* //需要加入的样式
.change {
    width: 300px;
    height: 300px;
}
*/
var ul = document.getElementsByTagName('ul')
var lis = document.getElementsByTagName('li') 
ul.style.display = 'none'
for(var i = 0; i < lis.length; i++) {
    lis[i].className = &#39;change&#39;;
     }
     ul.style.display = &#39;block&#39;
ログイン後にコピー

その他

1. イベント委任。ブラウザ イベントとバブル キャプチャを使用してページ イベント バインディングを削減し、特定のタイプのすべてのイベントを管理するイベント ハンドラー。イベント関数が多すぎると大量のメモリを占有し、イベントにバインドされる DOM 要素が増えると DOM アクセス数が増加し、ページのインタラクティブな準備時間も遅延します。

var frag = document.createDocumentFragment() //创建一个虚拟节点对象	
for(var i = 0; i < 10; i++) {				
    var li = document.createElement("li")		
    li.innerHTML = &#39;我是第&#39; + i + 1 + &#39;个元素&#39;		
    frag.appendChild(li)  //将li元素加到虚拟节点对象上
    } 			
    ul.appendChild(frag)  //将虚拟节点对象加到ul上
ログイン後にコピー

2. ループ内の最適化により dom 操作の回数が削減されます


// 事件委托前
var lis = document.getElementsByTagName(&#39;li&#39;)
for(var i = 0; i < lis.length; i++) {
   lis[i].onclick = function() {
      console.log(this.innerHTML)
   }}    // 利用浏览器事件通过父元素委托事件给子元素
   var ul = document.getElementsByTagName(&#39;ul&#39;)ul.onclick = function(event) {
	//也可以做判断给指定的子元素绑定事件
   console.log(event.target.innerHTML)};
ログイン後にコピー

こうやってみるとキャッシュノードの効果を体感できません以下の例を参照してください


//例子1:减少在计算过程中操作dom
// 优化前,访问了好多次dom,这些都是细节问题,有经验的绕过,小白平常多注意就行
for(var i = 0; i < 10; i++) {
    document.getElementById(&#39;el&#39;).innerHTML += &#39;1&#39;} 
    // 优化后 
    var str = &#39;&#39;for(var i = 0; i < 10; i++) {
    str += &#39;1&#39;}document.getElementById(&#39;el&#39;).innerHTML = str/
ログイン後にコピー

3. セレクターの違い


##要素を取得する最も一般的な方法は、getElementsByXXX() と queryselectorAll() の 2 つです。これら 2 つのセレクターの違いは非常に大きく、前者は動的コレクションを取得すること、後者は静的コレクションを取得することです

//不缓存
var ps = document.getElementsByTagName("p"), i, p;
for( i=0; i<ps.length; i++ ){  
    p = document.createElement("p");
    document.body.appendChild("p");
    }造成死循环,每次执行for循环都会动态获取ps的长度,而我们每次进入循环都增加了一个DOM(p),ps的长度也+1.
    //缓存
    var ps = document.getElementsByTagName("p"), i, p,len;
    for( i=0;len=ps.length;i<len; i++ ){  
        p = document.createElement("p");
        document.body.appendChild("p");
    }//使用变量保存ps的长度。
ログイン後にコピー

静的コレクションの操作ではドキュメントの再クエリが発生しません。動的コレクションよりも最適化されています。


推奨学習:

JavaScript ビデオ チュートリアル

以上がDom ノードを最適化する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:csdn.net
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート