ホームページ >ウェブフロントエンド >htmlチュートリアル >DOM_html/css_WEB-ITnose を最適化する
DOM 最適化の本質は、実際には DOM ツリーのリフローと再描画を減らすことです。リフローと再描画の理解については、「フロントエンド知識の普及のための HTML」を参照してください。
DOM の構造の最適化は、参照の保存、アニメーションの最適化、ノードの保存、ノードの更新などの基本的な操作にすぎません。 。
インターネットで HTML を閲覧していたとき、多くの人 (子供) が異口同音に、DOM ノードを取得したら必ず保存する必要があると言っていたことを思い出します。そうしないと、結果は醜いものになります。
なぜ~なぜ~なぜ~
いわゆるjsが実際にはDOM、BOM、ECMAの組み合わせの産物であることは誰もが知っています。 元々、私の JS は非常に高速でしたが、会話するには DOM にアクセスする必要がありました。 どうすればいいでしょうか? ドアをノックして DOM が応答するのを待つしかありません~しかし、待ち時間は非常に長いです。
デモを見てみましょう。
var times=10000;var time1 = function(){ var time = times; while(time--){ //DOM的两个操作放在循环内 var dom = document.querySelector("#Div1"); dom.innerHTML+="a"; }};var time2=function(){ var time = times, dom = document.querySelector("#Div1"); while(time--){ //DOM的一个操作放在循环内 dom.innerHTML+="a"; }};var time3=function(){ var time = times, dom = document.querySelector("#Div1"), str = ""; while(time--){ //循环内不放置DOM的操作 str +="a"; } dom.innerHTML=str;}console.time(1); //设置时间起点time1();console.timeEnd(1);console.time(2); //设置时间起点time2();console.timeEnd(2);console.time(3); //设置时间起点time3();console.timeEnd(3);//测试结果为:1: 101.868ms2: 101.560ms3: 13.615ms
もちろん、これは単なる誇張された例です。DOM を頻繁に操作する場合は、次のことを覚えておいてください。保存するために。 さらに、保存する場合は、DOM 関連の操作をすべて保存する必要があります。
たとえば、style、innerHTML、その他の属性。
これを行う原則は、リフローと再描画の数を減らすことです。
リフローと再描画は通常どのような状況で発生しますか?リフローが発生します:
表示可能な DOM 要素の追加または削除
要素の位置の変更
要素のサイズ変更
要素の内容が変更されます (例: テキストが異なるサイズの別の画像に置き換えられます)
ページ レンダリングの初期化 (これは不可避です) )
ブラウザウィンドウのサイズ変更
一般に、ページのレイアウトやサイズが変更された場合でもリフローが発生します。再塗装はいつ行われますか? リフローが発生すると必ず再描画が発生しますが、再描画の範囲はリフローよりも若干大きくなります。たとえば、フォントの色、ページの背景色、その他の比較的「表面的な」操作のみを変更する場合、リフローは妨げられません。
次のように操作すると、
div.style.color="red";div.style.border="1px solid red";
ブラウザは 2 つの再配置を 1 つにスマートにマージし、リソースを節約します。 実際、関数スロットルの考え方はこれと似ています。
var throttle = (function(){ var time; return function(fn,context){ clearTimeout(time); //进行函数的节流 time = setTimeout(fn.bind(context),200); }})()
この手法は通常、ブラウザのサイズを変更するときに使用されます。ただし、途中の場合は、offsetTop、clientTop などのプロパティにアクセスすると、すぐに実行されます。そうすれば、結果はあなたにとって何もありません。
div.style.color="red"; //积累一次重排记录var height = div.clientHeight; //触发重排div.style.border="1px solid red"; //再次积累一次重排
現時点では、ブラウザはあなたに騙されています。 したがって、ちょっとした提案は、DOM 構造を変更したい場合は、すべてを一度に完了するのが最善であるということです。または、すべてを完了したい場合は、上記の CSS 変更は次のように行うこともできます
div.style.cssText="color:red;border:1px solid red"; //覆盖原来的cssdiv.classList.add("change"); //利用class来整体改动
DOM 操作は単なる CRUD です。基本 API の簡単な紹介です
var div = document.createELement("div");
var divs = document.querySelectorAll('div'); //很多个,放在数组内var onlydiv = document.querySelector('div'); //只有一个//以及document.getElement系列
var html = div.innerHTML; var outer = div.outerHTML; //这两个是非常常用的var classNames = div.classList;var className = div.className;var tagName = div.tagName;var id = div.id;var style = div.getAttribute("style");//....
ele.replaceChild(replace,replaced); //replace代替replaced//添加子节点ele.appendChild(child);//删除子节点ele.removeChild(child);//插入子节点ele.insertBefore(newEle,referenceEle);
わかりました~ 実際、上記の API は、DOM 操作を伴う限り再配置されます。したがって、ここで最適化できます。
バッチで子ノードを追加する必要がある場合は、フラグメントの仮想フラグメントをコンテナとして使用する必要があります。 100 個の p タグを追加する必要があります
var times = 100;var addP = function(){ var time = times, tag1 = document.querySelector('#tag1'); while (time--) { var p = document.createElement('p'); tag1.appendChild(p); }}var useFrag = function(){ var time = times, tag1 = document.querySelector('#tag1'), frag = document.createDocumentFragment(); while (time--) { var p = document.createElement('p'); frag.appendChild(p); } tag1.appendChild(frag);}console.time(1);addP();console.timeEnd(1);console.time(2);useFrag();console.timeEnd(2);//基本事件差为:1: 1.352ms2: 0.685ms
フラグメント フラグメントを使用することに加えて、innerHTML と externalHTML を使用して、関連する最適化操作を実行することもできます。ここでは詳細には触れません
ここで言いたいことはあまりありません。絶対レイアウトの使用方法を学ぶだけです。 関連する UI 操作を実行するときに、誤って全画面表示が発生する可能性があることは間違いありません。たとえば、キャンパスの中古街のレイアウトでは、下にスクロールするとヘッダーバーが拡大され、レイアウトが悪いとページ全体が再配置されます。 (バカ、バカ、バカ、バカ)
彼はここで違います。彼はレイアウトに直接絶対値を使用し、ドキュメントの流れから離れ、過剰なページの再配置を防ぎます。
最後に:
最適化への道は長いので、気をつけてください~