## `DOM`優化
> * 優化節點修改。
>
>
> * 使用`cloneNode`在外部更新節點然后再通過`replace`與原始節點互換。
>
>
>
> ~~~
> var orig = document.getElementById('container');
> var clone = orig.cloneNode(true);
> var list = ['foo', 'bar', 'baz'];
> var content;
> for (var i = 0; i < list.length; i++) {
> content = document.createTextNode(list[i]);
> clone.appendChild(content);
> }
> orig.parentNode.replaceChild(clone, orig);
> ~~~
>
>
> * 優化節點添加
>
>
>
> > 多個節點插入操作,即使在外面設置節點的元素和風格再插入,由于多個節點還是會引發多次reflow。
>
>
> * 優化的方法是創建`DocumentFragment`,在其中插入節點后再添加到頁面。
>
>
> * 如`JQuery`中所有的添加節點的操作如`append`,都是最終調用`DocumentFragment`來實現的,
>
>
>
> ~~~
> createSafeFragment(document) {
> var list = nodeNames.split( "|" ),
> safeFrag = document.createDocumentFragment();
>
> if (safeFrag.createElement) {
> while (list.length) {
> safeFrag.createElement(
> list.pop();
> );
> };
> };
> return safeFrag;
> };
> ~~~
>
>
> * 優化`CSS`樣式轉換。
>
>
>
> > 如果需要動態更改CSS樣式,盡量采用觸發reflow次數較少的方式。
>
>
> * 如以下代碼逐條更改元素的幾何屬性,理論上會觸發多次`reflow`。
>
>
>
> ~~~
> element.style.fontWeight = 'bold' ;
> element.style.marginLeft= '30px' ;
> element.style.marginRight = '30px' ;
> ~~~
>
>
> * 可以通過直接設置元素的`className`直接設置,只會觸發一次`reflow`。
>
>
>
> ~~~
> element.className = 'selectedAnchor' ;
> ~~~
>
>
> * 減少`DOM`元素數量
>
>
> * 在`console`中執行命令查看`DOM`元素數量。
>
>
>
> ~~~
> `document.getElementsByTagName( '*' ).length`
> ~~~
>
>
> * 正常頁面的`DOM`元素數量一般不應該超過`1000`。
>
> * `DOM`元素過多會使`DOM`元素查詢效率,樣式表匹配效率降低,是頁面性能最主要的瓶頸之一。
> * `DOM`操作優化。
> * `DOM`操作性能問題主要有以下原因。
> * `DOM`元素過多導致元素定位緩慢。
> * 大量的`DOM`接口調用。
> * `JAVASCRIPT`和`DOM`之間的交互需要通過函數`API`接口來完成,造成延時,尤其是在循環語句中。
> * `DOM`操作觸發頻繁的`reflow(layout)`和`repaint`。
> * `layout`發生在`repaint`之前,所以layout相對來說會造成更多性能損耗。
> * `reflow(layout)`就是計算頁面元素的幾何信息。
> * `repaint`就是繪制頁面元素。
> * 對`DOM`進行操作會導致瀏覽器執行回流`reflow`。
> * 解決方案。
> * 純`JAVASCRIPT`執行時間是很短的。
> * 最小化`DOM`訪問次數,盡可能在js端執行。
> * 如果需要多次訪問某個`DOM`節點,請使用局部變量存儲對它的引用。
> * 謹慎處理`HTML`集合(`HTML`集合實時連系底層文檔),把集合的長度緩存到一個變量中,并在迭代中使用它,如果需要經常操作集合,建議把它拷貝到一個數組中。
> * 如果可能的話,使用速度更快的API,比如`querySelectorAll`和`firstElementChild`。
> * 要留意重繪和重排。
> * 批量修改樣式時,`離線`操作`DOM`樹。
> * 使用緩存,并減少訪問布局的次數。
> * 動畫中使用絕對定位,使用拖放代理。
> * 使用事件委托來減少事件處理器的數量。
> * 優化`DOM`交互 >在`JAVASCRIPT`中,`DOM`操作和交互要消耗大量時間,因為它們往往需要重新渲染整個頁面或者某一個部分。
> * 最小化`現場更新`。
> * 當需要訪問的`DOM`部分已經已經被渲染為頁面中的一部分,那么`DOM`操作和交互的過程就是再進行一次`現場更新`。
> * `現場更新`是需要針對`現場`(相關顯示頁面的部分結構)立即進行更新,每一個更改(不管是插入單個字符還是移除整個片段),都有一個性能損耗。
> * 現場更新進行的越多,代碼完成執行所花的時間也越長。
> * 多使用`innerHTML`。
> * 有兩種在頁面上創建`DOM`節點的方法:
> * 使用諸如`createElement()`和`appendChild()`之類的`DOM`方法。
> * 使用`innerHTML`。
> * 當使用`innerHTML`設置為某個值時,后臺會創建一個`HTML`解釋器,然后使用內部的`DOM`調用來創建`DOM`結構,而非基于`JAVASCRIPT`的`DOM`調用。由于內部方法是編譯好的而非解釋執行,故執行的更快。 >對于小的`DOM`更改,兩者效率差不多,但對于大的`DOM`更改,`innerHTML`要比標準的`DOM`方法創建同樣的`DOM`結構快得多。
> * 回流`reflow`。
>
>
> * 發生場景。
> * 改變窗體大小。
> * 更改字體。
> * 添加移除stylesheet塊。
> * 內容改變哪怕是輸入框輸入文字。
> * CSS虛類被觸發如 :hover。
> * 更改元素的className。
> * 當對DOM節點執行新增或者刪除操作或內容更改時。
>
> * 動態設置一個style樣式時(比如element.style.width="10px")。
>
> * 當獲取一個必須經過計算的尺寸值時,比如訪問offsetWidth、clientHeight或者其他需要經過計算的CSS值。
> * 解決問題的關鍵,就是限制通過DOM操作所引發回流的次數。
>
>
> * 在對當前DOM進行操作之前,盡可能多的做一些準備工作,保證N次創建,1次寫入。
>
> * 在對DOM操作之前,把要操作的元素,先從當前DOM結構中刪除:
>
> * 通過removeChild()或者replaceChild()實現真正意義上的刪除。
>
> * 設置該元素的display樣式為“none”。
>
> * 每次修改元素的style屬性都會觸發回流操作。
>
>
>
> ~~~
> element.style.backgroundColor = "blue";
> ~~~
>
>
> * 使用更改`className`的方式替換`style.xxx=xxx`的方式。
>
> * 使用`style.cssText = '';`一次寫入樣式。
>
> * 避免設置過多的行內樣式。
>
> * 添加的結構外元素盡量設置它們的位置為`fixed`或`absolute`。
>
> * 避免使用表格來布局。
>
> * 避免在`CSS`中使用`JavaScript expressions(IE only)`。
>
> * 將獲取的`DOM`數據緩存起來。這種方法,對獲取那些會觸發回流操作的屬性(比如`offsetWidth`等)尤為重要。
>
> * 當對HTMLCollection對象進行操作時,應該將訪問的次數盡可能的降至最低,最簡單的,你可以將length屬性緩存在一個本地變量中,這樣就能大幅度的提高循環的效率。