瀏覽器中的Dom
文檔對象模型Dom是獨立於語言的,用以操作XML和HTML文檔的程序接口(API)。在瀏覽器中的接口通常是以javascript操作的,因此大多數的腳本都在與DOM打交道。Dom和javascript兩個接口是獨立存在的。因此如果通過功能接口連接,就會產生較大的性能損害,連接的次數越多,對性能的損害就越大。
Dom的修改和訪問
訪問一次Dom,就會產生一定性能上的損失,修改Dom在性能上的損失更大。因爲會導致瀏覽器重新計算頁面的幾何變化。
innerHtml和Dom方法的比較:如果不考慮標準的問題,他們的性能上差別不大。但是在所有瀏覽器中innerHtml的速度要快的很多,除了基於webkit的(Chrome和safari)。
!!使用節點克隆代替creatElment();
Html集合:Html集合是一個類似數組的存放html元素的列表,常用的獲取Html集合有以下幾種方法(說實話用慣了框架在回頭看這些原生的東西真的有些陌生):
document.getElementById:
document.getElementsByTagName:
document.getElementsByClassName:(不支持IE8及IE8以下)
document.images
document.links
document.forms
這些方法返回的html collection對象是一個類似於數組的列表。他沒有數組的一些方法(push(),slice())等,但是通過.length可以返回這個列表的長度,通過索引值也可以獲取這個列表中的第N項。
HTML集合實際上是在查詢文檔,當你更新時,每次都會重複這個查詢操作,例如返回這個集合的長度,這是一個非常低效率的方法。遍歷同樣大小和內容的數組和html集合,遍歷數組的速度明顯較快。
!!解決辦法:
- 將HTML集合拷貝到一個數組中,通過遍歷數組
- 在每次迭代的訪問集合的長度的時候,都會導致集合更新,在瀏覽器中會導致性能的損失。可以將長度緩存在變量中
- 在迭代訪問的時候使用局部變量
抓取Dom
1.在新版本的瀏覽器中兩個方法的抓取速度差不多,但是老式的IE瀏覽器中,nexsibling的速度要比childNodes的速度要快。
2.使用children來代替childNodes
3.選擇器API,根據CSS選擇器查詢特定元素,比如document.querySelector()和querySelectorAll(),這兩個方法都是DOM節點的方法,因此支持子查詢。返回NodeList(包含匹配節點的類數組對象),NodeList對象是一個靜態列表,不會對應實時的文檔結構。
document.querySelector()//返回符合規則的第一個節點
querySelectorAll()//返回符合規則的所有節點
重繪和重排版
當瀏覽器下載並解析完HTML標記文件的Dom,Css,圖片,javascript之後,會生成兩個內部的數據結構:
- Dom樹(HTML的標籤結構)
渲染樹 爲每個Dom樹上每個需要顯示的節點分配一個內存,(隱藏的Dom節點不會分配內存),節點樹上的節點稱爲“框”,“盒”。一旦Dom樹和渲染樹構造完畢,瀏覽器就可以顯示這些元素了。
當DOM改變影響到元素的幾何高度和寬度時原有的渲染樹中受影響的部分的部分將失效,渲染樹進行重構,這個過程叫做重排版,經過一系列的渲染之後,瀏覽器在重繪進程中將渲染樹顯示到瀏覽器,這個過程叫做重繪。這些過程是及其損害瀏覽器的性能的。//之後改變盒模型時纔會進行重繪
下面的幾種情況會導致網頁重排版:
- 添加或者刪除可見的dom元素
- 元素位置發生改變
- 元素的盒模型改變
- 內容改變
- 瀏覽器窗口改變
當通過以上條件查詢並返回最新的值時,網頁會進行重排版:
優化原則:最小化重繪和重排
合併操作
el.style.borderLeft = “1px”;
el.style.borderRight = “2px”;
el.style.padding = “5px”;
可以優化爲:
el.style.cssText = “border-left:1px;border-right:2px;padding:5px;”
批量修改
將需要修改的dom從瀏覽器中脫離(定位),進行多重修改,在放回文檔流
三種方法:
- 隱藏元素,進行修改,顯示元素
- 將原始文本複製到一個脫離文檔的文本,進行操作在覆蓋原有的
- 使用絕對定位(但是會覆蓋下面的元素)