浅析 innerHTML 性能优化的原理
2023-09-11 14:19:23 时间
昨天看了 lveyo老兄的"innerHTML的性能问题" 一文 http://lveyo.iteye.com/blog/182891
该文介绍了一篇老外的关于提高innerHTML性能的文章.
老外的方法非常的怪异且神奇.
很多朋友在惊叹之余 对于背后的原理非常感兴趣.
受hax的提醒, 我看了一下webkit的代码.在这里我将分析的结果分享出来
说的不一定对 还请大家多多拍砖.
浏览器在 el.innerHTML = newHTML 时所做的工作:
====================================
原始方法
1) 创建一个fragment(document碎片)
2) 将 newHTML 设置到 fragment 内部 (这里怎么设置的不必关心,反正不是用的innerHTML 呵呵)
3) 清除el下的所有子节点 , 类似 el.removeChildren()
4) 将fragment加入到 el内, 类似 el.appendChild(fragment)
====================================
文章里的新方法
1)克隆el节点(不包含子节点),相当于
newEl=document.createElement(el.tagName);
然或将el的所有属性赋值给 newEl (通过 el.getAttribute newEl.setAttribute)
2) 创建一个fragment(document碎片)
3) 将 newHTML 设置到 fragment 内部 (这里怎么设置的不必关心,反正不是用的innerHTML 呵呵)
4) 清除 newEl 下的所有子节点 , 类似 newEl.removeChildren()
5) 将 fragment 加入到 newEl 内, 类似 newEl.appendChild(fragment)
6) 用 fragment 替换 el. 相当于 el.parentNode.replaceChild(newEl, el);
新方法看起来比原始方法更麻烦, 但是为什么速度会更快呢?
关键点就是在 新方法的步骤 4 5 6 .
首先看4:
newEl 是clone的el,但是没有子结点,所以removeChildren很快就返回.相当于没有执行.
而且就算newEL有子结点,由于newEl不是一个在dom树里的节点, 也省去了其中复杂的一步
- if (n->inDocument()) n->removedFromDocument();
if (n->inDocument()) n->removedFromDocument();
而 el.removeChildren 这个操作 相比之下自然要耗时很多.原因有三:removeChild操作比较复杂;el有子节点;el和el的子结点都在dom树内.
再来看5
newEl 和 fragment 本身都是脱离dom树独立存在的,这个操作速度也要比el.appendChild(fragment)快.
再来看6.
6的操作就是 在el.parentNode中移除el,然后再在原始位置加入newEl. 这个步骤并没有速度优势.
但是 4 5 6这3个操作加起来,当el和newHTML足够复杂时,还是要比原始方法的 3 4 步更快
以上就是我的分析 有不对的地方 欢迎大家抛砖.
同时欢迎大家来贴一下 IE 和 ff的实现方式
相关文章
- 使用HTML5监測站点性能
- DDS直接数字频率合成器的MATLAB性能仿真
- 【36】局部性原理:数据库性能跟不上,加个缓存就好了?
- 服务器Web性能测试主要包含四个方面
- 高级性能测试工程师面试必问十大问题
- 基于jmeter的性能全流程测试
- 国产CPU执行SPL实现数据库运算的性能实用性测试
- 《Hadoop MapReduce性能优化》一1.3 Hadoop MapReduce的工作原理
- 在服务端处理同步发送小消息的性能上Kafka>RocketMQ>RabbitMQ
- 基于JVM(内存)和Tomcat性能调优
- 关于性能测试模型的探讨
- AMD宣布修复RX480供电Bug 性能还提速3%
- 从食堂就餐看性能测试分析
- 性能测试知多少---性能测试工具原理与架构
- 秋色园QBlog技术原理解析:性能优化篇:读写分离与文本数据库(十八)
- 性能测试需求文档
- [转]nginx折腾记(HTTP性能能测试,与Apache对比)
- 面试官:MySQL索引底层数据结构原理与性能调优,你能回答多少?