各种动态渲染Element方式的性能分析

技术各种动态渲染Element方式的性能分析本篇内容介绍了“各种动态渲染Element方式的性能分析”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大

本文介绍了“各种动态绘制元素方法的性能分析”的知识。很多人在实际案例操作中都会遇到这样的困难。接下来,让边肖带领大家学习如何应对这些情况!希望大家认真阅读,学点东西!

一、性能优化的原则及方法论

原理:在动态渲染进入一个dom元素之前,首先要保证动态渲染操作对原Dom树的影响必须尽可能小,影响重绘和重排。

确定方法:我们必须找到一个容器来缓存渲染过程中生成的dom结构(操作必须对原始dom树影响尽可能小),然后再次将其渲染到目标元素。

二、生成期间DOM缓存的选择

文档片段(文档片段对象,选择原因:与文档流分离)

临时元素(选择原因:新元素与文档流分离)

临时元素内部HTML克隆代码返回最外面的元素对象,然后插入appendChild。如果需要,需要一个选择器方法来提取元素对象。

解析该XML字符串以生成一个Element对象(注意,它是一个Element对象,而不是一个HTMLxxxElement对象),然后该对象是appendChild。

创建元素,然后逐步渲染。

通过描述Dom的字符串(以下称为DomString),它被转换成一个Dom对象。

临时字符串(选择原因:用innerHTML呈现,一次呈现)

三、DocumentFragment的优缺点

基本模式:

var fragment=document . createdocumentfragment();Fragment.appendChild(.//life生成Element)//life示例,根据配置,创建元素varconfigvar={El name :' div ',ID 3360' blablabla ',name 3360' balbla ',class: ' ClassName(函数(Config){ varel=document . createelement(Config。ELname);El . class name=(Config . class | | ' ');for(letattrnameconfig){ if(AttrName=' class ')继续;el.setAttribute(AttrName,Config[AttrName]);} returnel})(配置变量)优势

1.与文档流分离,操作不会影响Dom树。

2.每次生成临时元素时,都可以保存元素对象的引用,无需多次使用选择器再次获取。

劣势

兼容性仅达到IE9。

四、createElement的优缺点

基本方式

varel=document.createElement

("ElementName");         el.className = "";     el.setAttribute("AttrName",AttrValue);     el.setAttribute("AttrName",AttrValue);     ...     el.appendChild(                   ... //生成Element的IIFE,见上文     );

优点

1、新创建的元素脱离于文档流,操作不会对Dom树产生影响

2、兼容性***

3、在每一次生成临时Element时候就可以将该Element对象的引用保存下来,而不需要多次用选择器再次获取。

缺点

每一次调用setAttribute方法都是一次次对Element进行修改,此处具有潜在的性能损耗。

五、DomString——临时Element+innerHTML+cloneNode的优缺点

基本模式

var domString2Dom = (function(){     if (window.HTMLTemplateElement){         var container = document.createElement("template");         return function(domString){             container.innerHTML = domString;             return container.content.firstChild.cloneNode(true)         }     }else{         //对不支持的template 的浏览器还有兼容性方法没写,所以不支持tr,td等些元素inner进div中。         var container = document.createElement("div");         return function(domString){             container.innerHTML = domString;             return container.firstChild.cloneNode(true)         }             } })();
var template = domString2Dom('<div class="TestClass" Arg="TestArg"></div>'); for (var index = 0; index < 80; index++) {       template.appendChild(     (function(){       var el = domString2Dom("<div>M</div>");       return el     })()   )                 }

优点

创建Dom之后不需要多次进行setAttribute

缺点

1、临时元素不能包裹一些特定的元素(不能在所有浏览器的所有 HTML 元素上设置 innerHTML 属性)

2、解析的过程进行了很多其余的操作。此处具有潜在的性能损耗。

3、插入的字符串***层Node只允许有一个元素

六、DomString&mdash;&mdash;XML解析的优缺点

基本模式

var XMLParser = function () {     var $DOMParser = new DOMParser();     return function (domString) {         if (domString[0] == "<") {             var doc = $DOMParser.parseFromString(domString, "application/xhtml+xml");             return doc.firstChild;         }         else {             return document.createTextNode(domString);         }     }; }();
var template = XMLParser('<div class="TestClass" Arg="TestArg"></div>'); for (var index = 0; index < 80; index++) {   template.appendChild((function () {     var el = XMLParser("<div>M</div>");     return el;   })()); }

优点

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

缺点

1、解析的过程本身就具有潜在的性能损耗。

2、只能得到刚刚创建最外层元素的克隆。子元素的引用还需要用选择器。

3、插入的字符串***层Node只允许有一个元素

七、临时字符串的优缺点

基本模式:

var template = document.createElement("div"); template.innerHTML = `<div class="TestClass" Arg="TestArg">                         Test TextNode                         ${(function(){                           var temp = new Array(8);                           for (var index = 0; index < 80; index++) {                             temp[index]="<div>M</div>"                           }                           return temp.join()                         }())}                       </div>` //需要增加的一大段Element

优点

1、通用性***,不需要逐步创建一大堆无用的Element对象引用

2、运用es6模板字符串编码优雅,不需要字符串用加号进行链接

缺点

1、如果是直接给出配置Config进行渲染需要进行字符串的生成

2、只能得到刚刚创建最外层元素的引用。子元素的引用还需要用选择器。

八、Template元素

由于HTML5中新增了template元素

其特点就是有一个content属性是HTMLDocumentFragment对象,所以可以包容任何元素

基本范式是:

var template = document.createElement("template"); template.innerHTML = `<div class="TestClass" Arg="TestArg">                         Test TextNode                         ${(function(){                           var temp = new Array(8);                           for (var index = 0; index < 80; index++) {                             temp[index]="<div>M</div>"                           }                           return temp.join()                         }())}                       </div>` //需要增加的一大段Element // template.content 是HTMLDocumentFragment

优点

比div要好很多,作为临时元素容器的包容性更强

缺点

在不支持的浏览器中表示为HTMLUnknownElement

九、各种方法的效率对比

测试代码:(由于笔者不太熟悉各种浏览器性能的BUG,这里的代码如果有不足请指正),代码由typescript进行编写,也可以用babel进行编译。

/**  * @param Count:渲染DOM结构的次数  */ var DateCount = {     TimeList : {},     time:function(Str){         console.time(Str);     },     timeEnd:function(Str){         console.timeEnd(Str);     } }; //==================工具函数====================== var domString2Dom = (function () {     var container;     if (window.HTMLTemplateElement) {         container = document.createElement("template");         return function (domString) {             container.innerHTML = domString;             return container.content.firstChild.cloneNode(true);         };     }     else {         //对不支持的template 的浏览器还有兼容性方法没写,所以不支持tr,td等些元素inner进div中。         container = document.createElement("div");         return function (domString) {             container.innerHTML = domString;             return container.firstChild.cloneNode(true);         };     } })(); var XMLParser = (function () {     var $DOMParser;     if (window.DOMParser) {         $DOMParser = new DOMParser();         return function (domString) {             if (domString[0] == "<") {                 var doc = $DOMParser.parseFromString(domString, "application/xhtml+xml");                 return doc.firstChild;             }             else {                 return document.createTextNode(domString);             }         };     }else{         $DOMParser = new ActiveXObject("Microsoft.XMLDOM");         return function (domString) {             if (domString[0] == "<") {                 $DOMParser.async = false;                 $DOMParser.loadXML(domString);                    return $DOMParser             }             else {                 return document.createTextNode(domString);             }                         }      }  })(); //===============================================  var Test = function(Count){     //保留这种写法,能够在移动端平台中不依靠控制台进行效率测试     // var DateCount = {     //     TimeList : {},     //     time:function(Str){     //         this.TimeList[Str] = Date.now();     //     },     //     timeEnd:function(Str){     //         alert(Str+(Date.now() - this.TimeList[Str]));     //     }     // }          //基准测试1:     DateCount.time("无临时div + 不需要字符串拼接 + innerHTML:")     for (let index = 0; index < Count; index++) {         (function(){             var template = document.createElement("div");                 template.className = "TestClass";                 template.setAttribute("Arg","TestArg")                 template.innerHTML = ` Test TextNode <div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div> <div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div> <div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div> <div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div> <div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div> <div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div> <div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div> <div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div> <div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div> <div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div> <div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div> <div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div> ` //需要增加的一大段Element,共100个子级div             return template         }())       }     DateCount.timeEnd("无临时div + 不需要字符串拼接 + innerHTML:")      //基准测试2:     DateCount.time("createElement+appendChild写法:")     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写法:")          //DocumentFragment      DateCount.time("DocumentFragment+ createElement+appendChild 写法:")     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 写法:")          //DomString&mdash;&mdash;临时Element+innerHTML+cloneNode     // DateCount.time("DomString&mdash;&mdash;临时Element+innerHTML+cloneNode:")     // for (let index = 0; index < Count; index++) {     //     (function(){     //         var template = domString2Dom('<div class="TestClass" Arg="TestArg"></div>');     //         for (let index = 0; index < 100; index++) {         //             template.appendChild(     //                 (function(){     //                     var el = domString2Dom("<div child='true'>M</div>");     //                     return el     //                 })()     //             )                     //         }     //         return template;     //     }())       // }     // DateCount.timeEnd("DomString&mdash;&mdash;临时Element+innerHTML+cloneNode:")          //DomString&mdash;&mdash;XML解析     // DateCount.time("DomString&mdash;&mdash;XML解析:")     // for (let index = 0; index < Count; index++) {     //     (function(){     //         var template = XMLParser('<div class="TestClass" Arg="TestArg"></div>');     //         for (let index = 0; index < 100; index++) {     //             template.appendChild((function () {     //                 var el = XMLParser("<div child='true'>M</div>");     //                 return el;     //             })());     //         }     //     }())       // }     // DateCount.timeEnd("DomString&mdash;&mdash;XML解析:")         //临时div + 临时字符串拼接:     DateCount.time("临时div + 字符串拼接:")     for (let index = 0; index < Count; index++) {         (function(){             let template = document.createElement("div");             template.innerHTML = `<div class="TestClass" Arg="TestArg">                                     Test TextNode                                     ${(function(){                                         let temp = "";                                         for (let index = 0; index < 100; index++) {                                             temp+="<div child='true'>M</div>"                                         }                                         return temp                                     }())}                                 </div>` //需要增加的一大段Element             return template.firstChild;          }())       }     DateCount.timeEnd("临时div + 字符串拼接:")      //临时template + 临时字符串拼接:     DateCount.time("临时template + 字符串拼接:")     for (let index = 0; index < Count; index++) {         (function(){             var template = document.createElement("template");             template.innerHTML = `<div class="TestClass" Arg="TestArg">                                     Test TextNode                                     ${(function(){                                         let temp = "";                                         for (let index = 0; index < 100; index++) {                                             temp+="<div child='true'>M</div>"                                         }                                         return temp                                     }())}                                 </div>` //需要增加的一大段Element             return template.content;          }())       }     DateCount.timeEnd("临时template + 字符串拼接:")      //临时template + createElement+appendChild 写法     DateCount.time("template + createElement+appendChild 写法:")     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)                         }                     return template;                 }());             return template.content          }())       }     DateCount.timeEnd("template + createElement+appendChild 写法:")  };  for (var key of [1,10,100,1000]) {     console.log("Start"+key);     Test(key); }

“各种动态渲染Element方式的性能分析”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注网站,小编将为大家输出更多高质量的实用文章!

内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/93967.html

(0)

相关推荐

  • Spring Security中如何进行用户信息UserDetails入门

    技术Spring Security中如何进行用户信息UserDetails入门Spring Security中如何进行用户信息UserDetails入门,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更

    攻略 2021年10月27日
  • C++中怎么使用工厂函数

    技术C++中怎么使用工厂函数本篇内容介绍了“C++中怎么使用工厂函数”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!如果在

    攻略 2021年11月29日
  • ADO.NET事务处理方法有哪些

    技术ADO.NET事务处理方法有哪些这篇文章主要介绍“ADO.NET事务处理方法有哪些”,在日常操作中,相信很多人在ADO.NET事务处理方法有哪些问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家

    攻略 2021年12月3日
  • 美国服务器提供的功能和优势

    技术美国服务器提供的功能和优势美国服务器相比其他地区的海外服务器拥有多种优势,包括安全性,速度和可靠性。美国服务器支持用户完全控制权限,并保护您的数据免受未经授权的访问。美国服务器还允许您轻松升级美配置及其服务。如有必要

    礼包 2021年12月16日
  • C++中指针引用的示例分析

    技术C++中指针引用的示例分析这篇文章主要介绍C++中指针引用的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!指针和引用形式上很好区别,但是他们似乎有相同的功能,都能够直接引用对象,对其进

    攻略 2021年11月11日
  • Hibernate会话工厂怎么建立

    技术Hibernate会话工厂怎么建立这篇文章主要讲解了“Hibernate会话工厂怎么建立”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Hibernate会话工厂怎么建

    攻略 2021年12月4日