zoukankan      html  css  js  c++  java
  • 浅析 innerHTML 性能优化的原理




    昨天看了 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树里的节点, 也省去了其中复杂的一步
    Java代码 复制代码 收藏代码
    1. 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的实现方式
  • 相关阅读:
    红黑树(RBTree)
    js闭包简要分析
    html 5的localstorag
    浅析CSS中的haslayout
    初识sass框架
    BFC块级格式化上下文简述
    RESTful互联网框架
    javascript的框架演化
    浅析angular框架的cookie
    angular template浅析
  • 原文地址:https://www.cnblogs.com/firstdream/p/5530048.html
Copyright © 2011-2022 走看看