日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
各種動(dòng)態(tài)渲染Element方式的性能探究

【引自雕刻零碎的博客】一、性能優(yōu)化的原則及方法論

樹(shù)立原則:動(dòng)態(tài)渲染進(jìn)入一個(gè)Dom元素,首先需要保證動(dòng)態(tài)渲染操作必須盡可能少對(duì)原有dom樹(shù)的影響,影響重繪及重排。

確定方法論:必須尋找一個(gè)容器來(lái)緩存渲染期間生成的dom結(jié)構(gòu)(操作必須盡可能少對(duì)原有dom樹(shù)的影響),然后再進(jìn)行一次渲染到目標(biāo)element中。

二、生成期間DOM緩存的選擇

  • DocumentFragment(文檔碎片對(duì)象,選擇原因:脫離于文檔流)
  • 臨時(shí)Element(選擇原因:新element脫離于文檔流)
    • createElement,再一步步進(jìn)行渲染
    • 通過(guò)描述Dom的String(下稱:DomString),轉(zhuǎn)化為Dom對(duì)象
      • 臨時(shí)Element+innerHTML+cloneNode返回最外層element元素對(duì)象,再進(jìn)行插入appendChild,必要時(shí)還需要選擇器方法講某一個(gè)Element對(duì)象提取出來(lái)
      • XML字符串通過(guò)解析生成Element對(duì)象(注意,不是HTMLxxxElement對(duì)象,是Element對(duì)象),然后將該對(duì)象appendChild進(jìn)去
  • 臨時(shí)字符串(選擇原因:借助innerHTML渲染,一次渲染)

三、DocumentFragment的優(yōu)缺點(diǎn)

基本模式:

 
 
 
  1. var fragment = document.createDocumentFragment(); 
  2.     fragment.appendChild( 
  3.         ...    //生成Element的IIFE 
  4.     )  
 
 
 
  1. //IIFE示例,根據(jù)配置創(chuàng)建元素 
  2. var ConfigVar = { 
  3.   ELname:"div", 
  4.   id:"blablabla", 
  5.   name:"balblabla", 
  6.   class:"ClassName" 
  7. (function(Config){ 
  8.       var el = document.createElement(Config.ELname); 
  9.           el.className = (Config.class || ""); 
  10.     for (let AttrName in Config){ 
  11.           if (AttrName == "class")continue; 
  12.           el.setAttribute(AttrName,Config[AttrName]); 
  13.     } 
  14.       return el; 
  15. })(ConfigVar)  

優(yōu)點(diǎn)

1、脫離于文檔流,操作不會(huì)對(duì)Dom樹(shù)產(chǎn)生影響

2、在每一次生成臨時(shí)Element時(shí)候就可以將該Element對(duì)象的引用保存下來(lái),而不需要多次用選擇器再次獲取。

缺點(diǎn)

兼容性只是達(dá)到IE9+

http://caniuse.com/#search=DocumentFragment

四、createElement的優(yōu)缺點(diǎn)

基本模式

 
 
 
  1. var el = document.createElement("ElementName");     
  2.     el.className = ""; 
  3.     el.setAttribute("AttrName",AttrValue); 
  4.     el.setAttribute("AttrName",AttrValue); 
  5.     ... 
  6.     el.appendChild(         
  7.           ... //生成Element的IIFE,見(jiàn)上文 
  8.     );  

優(yōu)點(diǎn)

1、新創(chuàng)建的元素脫離于文檔流,操作不會(huì)對(duì)Dom樹(shù)產(chǎn)生影響

2、兼容性***

3、在每一次生成臨時(shí)Element時(shí)候就可以將該Element對(duì)象的引用保存下來(lái),而不需要多次用選擇器再次獲取。

缺點(diǎn)

每一次調(diào)用setAttribute方法都是一次次對(duì)Element進(jìn)行修改,此處具有潛在的性能損耗。

五、DomString——臨時(shí)Element+innerHTML+cloneNode的優(yōu)缺點(diǎn)

基本模式

 
 
 
  1. var domString2Dom = (function(){ 
  2.     if (window.HTMLTemplateElement){ 
  3.         var container = document.createElement("template"); 
  4.         return function(domString){ 
  5.             container.innerHTML = domString; 
  6.             return container.content.firstChild.cloneNode(true) 
  7.         } 
  8.     }else{ 
  9.         //對(duì)不支持的template 的瀏覽器還有兼容性方法沒(méi)寫(xiě),所以不支持tr,td等些元素inner進(jìn)div中。 
  10.         var container = document.createElement("div"); 
  11.         return function(domString){ 
  12.             container.innerHTML = domString; 
  13.             return container.firstChild.cloneNode(true) 
  14.         }         
  15.     } 
  16. })();  
 
 
 
  1. var template = domString2Dom('
'); 
  • for (var index = 0; index < 80; index++) {     
  •   template.appendChild( 
  •     (function(){ 
  •       var el = domString2Dom("
    M
    "); 
  •       return el 
  •     })() 
  •   )                 
  • }  
  • 優(yōu)點(diǎn)

    創(chuàng)建Dom之后不需要多次進(jìn)行setAttribute

    缺點(diǎn)

    1、臨時(shí)元素不能包裹一些特定的元素(不能在所有瀏覽器的所有 HTML 元素上設(shè)置 innerHTML 屬性)

    2、解析的過(guò)程進(jìn)行了很多其余的操作。此處具有潛在的性能損耗。

    3、插入的字符串***層Node只允許有一個(gè)元素

    六、DomString——XML解析的優(yōu)缺點(diǎn)

    基本模式

     
     
     
    1. var XMLParser = function () { 
    2.     var $DOMParser = new DOMParser(); 
    3.     return function (domString) { 
    4.         if (domString[0] == "<") { 
    5.             var doc = $DOMParser.parseFromString(domString, "application/xhtml+xml"); 
    6.             return doc.firstChild; 
    7.         } 
    8.         else { 
    9.             return document.createTextNode(domString); 
    10.         } 
    11.     }; 
    12. }();  
     
     
     
    1. var template = XMLParser('
    '); 
  • for (var index = 0; index < 80; index++) { 
  •   template.appendChild((function () { 
  •     var el = XMLParser("
    M
    "); 
  •     return el; 
  •   })()); 
  • }  
  • 優(yōu)點(diǎn)

    DomString方法中通用性***的,雖然IE10+才支持DOMParser,但是IE9以下的有替代方法

    缺點(diǎn)

    1、解析的過(guò)程本身就具有潛在的性能損耗。

    2、只能得到剛剛創(chuàng)建最外層元素的克隆。子元素的引用還需要用選擇器。

    3、插入的字符串***層Node只允許有一個(gè)元素

    七、臨時(shí)字符串的優(yōu)缺點(diǎn)

    基本模式:

     
     
     
    1. var template = document.createElement("div"); 
    2. template.innerHTML = ` 
    3.                         Test TextNode 
    4.                         ${(function(){ 
    5.                           var temp = new Array(8); 
    6.                           for (var index = 0; index < 80; index++) { 
    7.                             temp[index]="
      M
    8.                           } 
    9.                           return temp.join() 
    10.                         }())} 
    11.                       
    ` //需要增加的一大段Element  

    優(yōu)點(diǎn)

    1、通用性***,不需要逐步創(chuàng)建一大堆無(wú)用的Element對(duì)象引用

    2、運(yùn)用es6模板字符串編碼優(yōu)雅,不需要字符串用加號(hào)進(jìn)行鏈接

    缺點(diǎn)

    1、如果是直接給出配置Config進(jìn)行渲染需要進(jìn)行字符串的生成

    2、只能得到剛剛創(chuàng)建最外層元素的引用。子元素的引用還需要用選擇器。

    八、Template元素

    由于HTML5中新增了template元素

    其特點(diǎn)就是有一個(gè)content屬性是HTMLDocumentFragment對(duì)象,所以可以包容任何元素

    基本范式是:

     
     
     
    1. var template = document.createElement("template"); 
    2. template.innerHTML = ` 
    3.                         Test TextNode 
    4.                         ${(function(){ 
    5.                           var temp = new Array(8); 
    6.                           for (var index = 0; index < 80; index++) { 
    7.                             temp[index]="
      M
    8.                           } 
    9.                           return temp.join() 
    10.                         }())} 
    11.                       
    ` //需要增加的一大段Element 
  • // template.content 是HTMLDocumentFragment  
  • 優(yōu)點(diǎn)

    比div要好很多,作為臨時(shí)元素容器的包容性更強(qiáng)

    缺點(diǎn)

    兼容性不好:http://caniuse.com/#search=HTML%20templates 在不支持的瀏覽器中表示為HTMLUnknownElement

    九、各種方法的效率對(duì)比

    測(cè)試代碼:(由于筆者不太熟悉各種瀏覽器性能的BUG,這里的代碼如果有不足請(qǐng)指正),代碼由typescript進(jìn)行編寫(xiě),也可以用babel進(jìn)行編譯。

     
     
     
    1. /** 
    2.  * @param Count:渲染DOM結(jié)構(gòu)的次數(shù) 
    3.  */ 
    4. var DateCount = { 
    5.     TimeList : {}, 
    6.     time:function(Str){ 
    7.         console.time(Str); 
    8.     }, 
    9.     timeEnd:function(Str){ 
    10.         console.timeEnd(Str); 
    11.     } 
    12. }; 
    13. //==================工具函數(shù)====================== 
    14. var domString2Dom = (function () { 
    15.     var container; 
    16.     if (window.HTMLTemplateElement) { 
    17.         container = document.createElement("template"); 
    18.         return function (domString) { 
    19.             container.innerHTML = domString; 
    20.             return container.content.firstChild.cloneNode(true); 
    21.         }; 
    22.     } 
    23.     else { 
    24.         //對(duì)不支持的template 的瀏覽器還有兼容性方法沒(méi)寫(xiě),所以不支持tr,td等些元素inner進(jìn)div中。 
    25.         container = document.createElement("div"); 
    26.         return function (domString) { 
    27.             container.innerHTML = domString; 
    28.             return container.firstChild.cloneNode(true); 
    29.         }; 
    30.     } 
    31. })(); 
    32. var XMLParser = (function () { 
    33.     var $DOMParser; 
    34.     if (window.DOMParser) { 
    35.         $DOMParser = new DOMParser(); 
    36.         return function (domString) { 
    37.             if (domString[0] == "<") { 
    38.                 var doc = $DOMParser.parseFromString(domString, "application/xhtml+xml"); 
    39.                 return doc.firstChild; 
    40.             } 
    41.             else { 
    42.                 return document.createTextNode(domString); 
    43.             } 
    44.         }; 
    45.     }else{ 
    46.         $DOMParser = new ActiveXObject("Microsoft.XMLDOM"); 
    47.         return function (domString) { 
    48.             if (domString[0] == "<") { 
    49.                 $DOMParser.async = false; 
    50.                 $DOMParser.loadXML(domString);    
    51.                 return $DOMParser 
    52.             } 
    53.             else { 
    54.                 return document.createTextNode(domString); 
    55.             }                 
    56.         } 
    57.  
    58.     } 
    59.  
    60. })(); 
    61. //=============================================== 
    62.  
    63. var Test = function(Count){ 
    64.     //保留這種寫(xiě)法,能夠在移動(dòng)端平臺(tái)中不依靠控制臺(tái)進(jìn)行效率測(cè)試 
    65.     // var DateCount = { 
    66.     //     TimeList : {}, 
    67.     //     time:function(Str){ 
    68.     //         this.TimeList[Str] = Date.now(); 
    69.     //     }, 
    70.     //     timeEnd:function(Str){ 
    71.     //         alert(Str+(Date.now() - this.TimeList[Str])); 
    72.     //     } 
    73.     // } 
    74.  
    75.         //基準(zhǔn)測(cè)試1: 
    76.     DateCount.time("無(wú)臨時(shí)div + 不需要字符串拼接 + innerHTML:") 
    77.     for (let index = 0; index < Count; index++) { 
    78.         (function(){ 
    79.             var template = document.createElement("div"); 
    80.                 template.className = "TestClass"; 
    81.                 template.setAttribute("Arg","TestArg") 
    82.                 template.innerHTML = ` Test TextNode 
    83. M
    M
    M
    M
    M
    M
    M
    M
    M
  • MMMMMMMMM
  • MMMMMMMMM
  • MMMMMMMMM
  • MMMMMMMMM
  • MMMMMMMMM
  • MMMMMMMMM
  • MMMMMMMMM
  • MMMMMMMMM
  • MMMMMMMMM
  • MMMMMMMMM
  • MMMMMMMMM
  • ` //需要增加的一大段Element,共100個(gè)子級(jí)div 
  •             return template 
  •         }())   
  •     } 
  •     DateCount.timeEnd("無(wú)臨時(shí)div + 不需要字符串拼接 + innerHTML:") 
  •  
  •     //基準(zhǔn)測(cè)試2: 
  •     DateCount.time("createElement+appendChild寫(xiě)法:") 
  •     for (let index = 0; index < Count; index++) { 
  •         (function(){ 
  •             var template = document.createElement("div"); 
  •                 template.className = "TestClass"; 
  •                 template.setAttribute("Arg","TestArg") 
  •  
  •                 template.appendChild(document.createTextNode('Test TextNode')); 
  •                 for (let index = 0; index < 100; index++) { 
  •                     let element = document.createElement("div"); 
  •                         element.setAttribute("child","true"); 
  •                         element.appendChild(document.createTextNode("M")) 
  •                         template.appendChild(element) 
  •                 } 
  •             return template 
  •         }())   
  •     } 
  •     DateCount.timeEnd("createElement+appendChild寫(xiě)法:")     
  •  
  •     //DocumentFragment  
  •     DateCount.time("DocumentFragment+ createElement+appendChild 寫(xiě)法:") 
  •     for (let index = 0; index < Count; index++) { 
  •         (function(){ 
  •             var fragment = document.createDocumentFragment(); 
  •                 fragment.appendChild(function(){ 
  •                     var template = document.createElement("div"); 
  •                         template.className = "TestClass"; 
  •                         template.setAttribute("Arg","TestArg") 
  •  
  •                         template.appendChild(document.createTextNode('Test TextNode')); 
  •                         for (let index = 0; index < 100; index++) { 
  •                             let element = document.createElement("div"); 
  •                                 element.setAttribute("child","true"); 
  •                                 template.appendChild(element) 
  •                         } 
  •                     return template; 
  •                 }()); 
  •  
  •             return fragment 
  •         }())   
  •     } 
  •     DateCount.timeEnd("DocumentFragment+ createElement+appendChild 寫(xiě)法:")     
  •  
  •     //DomString——臨時(shí)Element+innerHTML+cloneNode 
  •     // DateCount.time("DomString——臨時(shí)Element+innerHTML+cloneNode:") 
  •     // for (let index = 0; index < Count; index++) { 
  •     //     (function(){ 
  •     //         var template = domString2Dom(''); 
  •     //         for (let index = 0; index < 100; index++) {     
  •     //             template.appendChild( 
  •     //                 (function(){ 
  •     //                     var el = domString2Dom("M"); 
  •     //                     return el 
  •     //                 })() 
  •     //             )                 
  •     //         } 
  •     //         return template; 
  •     //     }())   
  •     // } 
  •     // DateCount.timeEnd("DomString——臨時(shí)Element+innerHTML+cloneNode:")     
  •  
  •     //DomString——XML解析 
  •     // DateCount.time("DomString——XML解析:") 
  •     // for (let index = 0; index < Count; index++) { 
  •     //     (function(){ 
  •     //         var template = XMLParser(''); 
  •     //         for (let index = 0; index < 100; index++) { 
  •     //             template.appendChild((function () { 
  •     //                 var el = XMLParser("M"); 
  •     //                 return el; 
  •     //             })()); 
  •     //         } 
  •     //     }())   
  •     // } 
  •     // DateCount.timeEnd("DomString——XML解析:")    
  •  
  •     //臨時(shí)div + 臨時(shí)字符串拼接: 
  •     DateCount.time("臨時(shí)div + 字符串拼接:") 
  •     for (let index = 0; index < Count; index++) { 
  •         (function(){ 
  •             let template = document.createElement("div"); 
  •             template.innerHTML = ` 
  •                                     Test TextNode 
  •                                     ${(function(){ 
  •                                         let temp = ""; 
  •                                         for (let index = 0; index < 100; index++) { 
  •                                             temp+="M" 
  •                                         } 
  •                                         return temp 
  •                                     }())} 
  •                                 ` //需要增加的一大段Element 
  •             return template.firstChild; 
  •          }())   
  •     } 
  •     DateCount.timeEnd("臨時(shí)div + 字符串拼接:") 
  •  
  •     //臨時(shí)template + 臨時(shí)字符串拼接: 
  •     DateCount.time("臨時(shí)template + 字符串拼接:") 
  •     for (let index = 0; index < Count; index++) { 
  •         (function(){ 
  •             var template = document.createElement("template"); 
  •             template.innerHTML = ` 
  •                                     Test TextNode 
  •                                     ${(function(){ 
  •                                         let temp = ""; 
  •                                         for (let index = 0; index < 100; index++) { 
  •                                             temp+="M" 
  •                                         } 
  •                                         return temp 
  •                                     }())} 
  •                                 ` //需要增加的一大段Element 
  •             return template.content; 
  •          }())   
  •     } 
  •     DateCount.timeEnd("臨時(shí)template + 字符串拼接:") 
  •  
  •     //臨時(shí)template + createElement+appendChild 寫(xiě)法 
  •     DateCount.time("template + createElement+appendChild 寫(xiě)法:") 
  •     for (let index = 0; index < Count; index++) { 
  •         (function(){ 
  •             var template = document.createElement("template"); 
  •                 template.appendChild(function(){ 
  •                     var template = document.createElement("div"); 
  •                         template.className = "TestClass"; 
  •                         template.setAttribute("Arg","TestArg") 
  •  
  •                         template.appendChild(document.createTextNode('Test TextNode')); 
  •                         for (let index = 0; index < 100; index++) { 
  •                             let element = document.createElement("div"); 
  •                                 element.setAttribute("child","true"); 
  •                                 template.appendChild(element) 
  •                         } 
  •                     retur
    當(dāng)前名稱:各種動(dòng)態(tài)渲染Element方式的性能探究
    地址分享:http://m.5511xx.com/article/djojpjd.html