日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > HTML >内容正文

HTML

160826、浏览器渲染页面过程描述,DOM编程技巧以及重排和重绘

發(fā)布時間:2024/7/19 HTML 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 160826、浏览器渲染页面过程描述,DOM编程技巧以及重排和重绘 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

一、瀏覽器渲染頁過程描述

?

1、瀏覽器解析html源碼,然后創(chuàng)建一個DOM樹。

在DOM樹中,每一個HTML標簽都有一個對應的節(jié)點(元素節(jié)點),并且每一個文本也都有一個對應的節(jié)點(文本節(jié)點)。

DOM樹的根節(jié)點就是documentElement,對應的是html標簽。

?

2、瀏覽器解析CSS代碼,計算出最終的樣式數(shù)據(jù)。

對CSS代碼中非法的語法它會直接忽略掉。

解析CSS的時候會按照如下順序來定義優(yōu)先級:瀏覽器默認設置,用戶設置,外聯(lián)樣式,內聯(lián)樣式,html中的style(嵌在標簽中的行間樣式)。

?

3、創(chuàng)建完DOM樹并得到最終的樣式數(shù)據(jù)之后,構建一個渲染樹。

渲染樹和DOM樹有點像,但是有區(qū)別。DOM樹完全和html標簽一一對應,而渲染樹會忽略不需要渲染的元素(head、display:none的元素)。

渲染樹中每一個節(jié)點都存儲著對應的CSS屬性。

?

4、當渲染樹創(chuàng)建完成之后,瀏覽器就可以根據(jù)渲染樹直接把頁面繪制到屏幕上。

?

二、高性能Javascript DOM編程

?

我們知道,用腳本進行DOM操作的代價很昂貴。把DOM和ECMAScript各自想象為一個島嶼,它們之間用收費橋梁鏈接,ECMAScript每次訪問DOM,都要經(jīng)過這座橋,并交納“過橋費”,訪問DOM的次數(shù)越多,費用也就越高。因此,推薦的做法是盡量減少過橋的次數(shù),努力呆在ECMAScript島上。這是比喻非常形象。那么怎樣才能高效呢?

?

1、DOM訪問與修改

訪問DOM元素是有代價的(這里其實和ajax調后臺數(shù)據(jù)接口是一樣,DOM是用于操作XML和HTML文檔的應用程序接口,一次能完成的事不要請求多次),通過DOM獲取元素之后,修改元素的代價更是昂貴,因為它會導致瀏覽器重新計算頁面的幾何變化(重排和重繪)。

例子:

var times = 15000;

//code1

console.time('time1');

for(var i=0; i<times; i++){

  document.getElementById('myDiv1').innerHTML +='a';

}

console.timeEnd('time1');

?

//code2

console.time('time2');

var str = '';

for(var i=0; i<times; i++){

  str += 'a';

}

document.getElementById('maDiv2').innerHTML = str;

console.timeEnd('time2');

結果time1:2352.064ms/time2:0.789ms

第一段代碼的問題在于,每次循環(huán)迭代,改元素都會被訪問兩次:一次讀取innerHTML的值,另一次重寫它。

結果充分證明,訪問DOM的次數(shù)越多,代碼的運行速度越慢。

因此,能減少DOM訪問的次數(shù)就盡量減少,盡量留在ECMAScript這端處理。

?

2、html集合&遍歷DOM

操作DOM另一個耗能點就是遍歷DOM,在平時獲取一組元素的時候(getElementsByTagName方法),收集的結果是一個類數(shù)組對象,它處于一種“實時狀態(tài)”實時存在,這意味著當?shù)讓游臋n對象更新時,它也會自動更新。

例子:

而這正是低效之源!很簡單,跟數(shù)組的優(yōu)化操作一樣,緩存一個length變量就OK了(讀取一個集合的length比讀取一個普通數(shù)組的length要慢很多,因為每次都要查詢):

console.time('time0');

var lis0 = document.getElementsByTagName('li');

var str0 = '';

for(var i=0; i<lis0.length; i++){

  str0 +=lis0[i].innerHTML;

}

console.timeEnd('time0');

console.time('time1');

?

var lis1 = document.getElementsByTagName('li');

var str1 = '';

for(var i=0; len=lis1.length; i<len; i++){

  str1 += lis1[i].innerHTML;

}

console.timeEnd('time1');

結果:time0:0.237ms/time1:0.099ms

當獲取的這個類數(shù)組對象長度值特別大的時候(如1000),性能提升還是很明顯的。

第一部分主要提了兩點優(yōu)化,一是盡量減少DOM的訪問,把運算放在ECMAScript這一端,二是盡量緩存局部變量,比如類數(shù)組對象的length。

?

三、重排和重繪

1、什么是重排和重繪

瀏覽器下載完頁面中的所有組件(html標記、Javascript、CSS、圖片)之后會解析生成兩個內部數(shù)據(jù)結構——DOM樹和渲染樹。

DOM樹表示頁面結構,渲染樹表示DOM節(jié)點如何顯示。DOM樹中的每一個需要顯示的節(jié)點在渲染樹中至少存在一個對應的節(jié)點(隱藏的DOM元素 display:none 在渲染樹中沒有對應的節(jié)點)。

渲染樹中的節(jié)點被稱為‘幀’或‘盒’,符合CSS模型的定義,頁面元素為一個具有填充,邊距,邊框和位置的盒子。一旦DOM樹和渲染樹構建完成,瀏覽器就開始繪制頁面元素。

當DOM的變化影響了元素的幾何屬性(寬或高),瀏覽器需要重新計算元素的幾何屬性,同時其他元素的幾何屬性和位置也會受到影響。瀏覽器會使渲染樹中受到影響的部分失效,并重新構造渲染樹,這個過程稱為重排。完成重排后,瀏覽器會重新繪制受到影響的部分到屏幕,這個過程稱為重繪。

由于瀏覽器的流布局,對渲染樹的計算通常只需要遍歷一次就可以完成。table及其內部元素除外,它可能需要多次計算才能確定好其在渲染樹中節(jié)點的屬性,通常要花三倍同等元素的時間。這也是為什么我們要避免使用table做布局的一個原因。

并不是所有的DOM變化都會影響幾何屬性,比如改變一個元素的背景色并不會影響元素的寬和高,這種情況下只會發(fā)生重繪。

?

2、重排何時發(fā)生

a、添加或刪除可見的DOM元素

b、元素位置改變

c、元素尺寸改變

d、元素內容改變

e、頁面渲染初始化

f、瀏覽器窗口尺寸改變

?

3、渲染樹變化的排隊和刷新

獲取布局信息的操作會導致隊列刷新,比如:

a、offsetTop,offsetLeft,offsetWidth,offsetHeight

b、scrollTop,scrollLeft,scrollWidth,scrollHeight

c、clientTop,clientLeft,clientWidth,clientHeight

d、getComputeStyle()||currentStyle(IE)

因為offsetHeight屬性需要返回最新的布局信息,因此瀏覽器不得不執(zhí)行渲染隊列中的“待處理變化”并觸發(fā)重排以返回正確的值(即使隊列中 改變的樣式屬性和想要獲取的屬性值并沒有什么關系)。

?

4、最小化重排和重繪

改變元素多種樣式的時候,最好用className,一次性完成操作,這樣只會修改一次DOM。

?

5、文檔碎片

文檔碎片的設計初衷就是為完成這類任務——更新和移動節(jié)點。當你附加一個片段到節(jié)點時,實際上被添加的是該片段的子節(jié)點,而不是片段本身。只會觸發(fā)一次重排,而且只訪問一次實時的DOM。

用法:

var oFragment = document.createDocumentFragment();

for(var i=0; i<1000; i++){

  var oP = document.createElement('p');

  oP.innerHTML = i;

  oFragment.appendChild(oP);

}

var oDo = document.body;

oDo.appendChild(oFragment);

?

6、讓動畫脫離文檔流

使用絕對位置定位頁面上的動畫元素,將其脫離文檔流。這樣不會導致文檔流中的元素受到影響,不會大規(guī)模的進行重排和重繪。

第二部分重排和重繪是DOM編程中耗能的主要原因之一,為了避免不必要的性能損耗可以參考一下幾點:

  • 盡量不要在布局信息改變時做查詢(會導致渲染隊列強制刷新);

  • 同一個DOM的多個屬性改變可以寫在一起(減少DOM訪問,同時把強制渲染隊列刷新的風險降為0);

  • 如果要批量添加DOM,可以先讓元素脫離文檔流,操作完成后帶人文檔流,這樣只會觸發(fā)一次重排(fragment元素的應用);

  • 將需要多次重排的元素,添加定位屬性,設置為absolute,fixed,這樣此元素就脫離了文檔流,不會影響其他元素。

  • ?

    轉載于:https://www.cnblogs.com/zrbfree/p/5818627.html

    總結

    以上是生活随笔為你收集整理的160826、浏览器渲染页面过程描述,DOM编程技巧以及重排和重绘的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內容還不錯,歡迎將生活随笔推薦給好友。