html页面显示过程

  • 解析HTML,并生成一棵DOM tree
  • 解析各种样式并结合DOM tree生成一棵Render tree
  • 对Render tree的各个节点计算布局信息,比如box的位置与尺寸
  • 根据Render tree并利用浏览器的UI层进行绘制流程。

其中,第三步,对render tree的各个结点计算布局信息为时间占用较大的一部分,而在这一步中,包含了layout,layout操作,是对render tree中对象的大小、尺寸进行计算,在默认情况下,浏览器的layout为lazy模式,也就是说,并非每次我们对DOM进行修改时都会layout,而是将这些修改存储在一个队列中,在一定的情况下统一提交队列,进而实现layout操作。

1.批量读写
当我们需要获取某一属性,这一属性需要计算才能得到,并且队列中存在尚未提交的DOM修改操作,则此时,DOM修改操作的队列将会被提交。
为了提高效率,减少更新render tree的次数,可以先统一读取属性,然后统一修改DOM,这样,就可以减少更新render tree的次数。

2.虚拟结点
当我们需要对DOM做出大量修改时,可以先创建一个虚拟结点,将所有修改附加在该节点,最后将该虚拟节点一次性提交给在render tree上存在的结点,则相当于只提交了一次修改操作。

3.查找元素的优化
因为ID是唯一的,也有原始的方法,因此使用ID查找元素是最快的,其次的是根据类和类型查找元素,通过属性查找元素是最慢的,因此应该尽可能的通过ID或者类来查找元素,避免通过类来查找元素。

4.改变DOM,包括添加,修改,删除DOM
改变DOM就会引起浏览器渲染,而渲染是相当慢的,因此应该避免不必要的渲染。

5.改变DOM的样式类等
改变DOM元素的样式,类也会导致浏览器渲染,因此也应该减少不必要的操作。

6.减少iframe
iframe需要消耗大量的时间,并阻塞下载,应该少用。

7.样式放在head中,脚本放在关闭标签</body>之前
样式放在head中,可以加快渲染,脚本放在关闭标签</body>之前可以加快下载速度,不免阻塞下载。

1. 批量增加Dom

尽量使用修改innerHTML的方式而不是用appendChild的方式; 因为使用innerHTML开销更小,速度更快,同时也更加内存安全.

有一点需要注意的是,用innerHTML方式添加时,一定不要在循环中使用 innerHTML += 的方式添加,这样反而会使速度减慢; 而是应该中间用array缓存起来,循环结束后调用 xx.innerHTML = array.join(‘’);的方式,或者至少保存到string中再插到innerHTML中.

针对用户列表一块采用这种方式优化后,加载速度提升一倍.

2. 单个增加Dom

这里是指要将新节点加载到一个内容不断变化的节点的情形,对于内容稳定的节点来说,随便怎么加都没有问题. 但是对于有动态内容的节点来说,为其添加子节点尽量使用 dom append的方式.

这是因为,dom append不会影响到其他的节点;而如果修改innerHTML属性的话,该父节点的所有子节点都会从dom树中剥离,再根据新的innerHTML值来重绘子节点dom树;所有注册到原来子节点的事件也会失效.

综上,如果在一个有动态内容的节点上 出现了 innerHTML += 的代码,就该考虑是否有问题了.

3. 创建Dom节点

用 createElement方式创建一个dom节点,有一个很重要的细节: 在执行完createElement代码之后,应该马上append到dom树中; 否则,如果在将这个孤立节点加载到dom树之前所做的赋值它的属性和innerHTML的操作都会引发该dom片段内存无法回收的问题. 这个不起眼细节,一旦遇到大量dom增删操作,就会引发内存的灾难.

4. 删除Dom节点

删除dom节点之前,一定要删除注册在该节点上的事件,不管是用observe方式还是用attachEvent方式注册的事件,否则将会产生无法回收的内存.

另,在removeChild和innerHTML=’’二者之间,尽量选择后者. 因为在sIEve(内存泄露监测工具)中监测的结果是用removeChild无法有效地释放dom节点.

5. 创建事件监听

现有的js库都采用observe方式来创建事件监听,其实现上隔离了dom对象和事件处理函数之间的循环引用,所以应该尽量采用这种方式来创建事件监听.

6. 监听动态元素

Dom 事件默认是向上冒泡的,发生在子节点中的事件,可以由父节点来处理. Event的 target/srcElement 仍是产生事件的最深层子节点. 这样,对于内容动态增加并且子节点都需要相同的事件处理函数的情况,可以把事件注册上提到父节点上,这样就不需要为每个子节点注册事件监听了.

同时,这样做也避免了产生无法回收的内存.即使是用Prototype的observe方式注册事件并在删除节点前调用stopObserving,也会产生出少量无法回收的内存,所以应该尽量少的为dom节点注册事件监听.

所以,当代码中出现在循环里注册事件时,也是我们该考虑事件上提机制的时候了.

最新文章

  1. 给Eclipse提速的7个技巧
  2. Winform控件重写
  3. 免费素材:包含 250+ 组件的 DO UI Kit
  4. svn使用方法介绍(1)
  5. PHP的GD 支持和加载MySQL功能
  6. {Reship}{C#}{GDI+}GDI+画笔,线,区域类型
  7. 集算器协助java处理多样性数据源之MongoDB
  8. csu 1306 Manor(优先队列)
  9. Winform- DotNetBar for Windows Forms的安装的添加
  10. C++重载流插入运算符和流提取运算符【转】
  11. smarty中判断一个变量是否存在于一个数组中或是否存在于一个字符串中?
  12. 基于以太坊开发的类似58同城的DApp开发与应用案例
  13. daily english dictation 学习笔记[1-10]
  14. git reset 和 git revert 使用区别
  15. 4-13 object类,继承和派生( super) ,钻石继承方法
  16. DFS Tempter of the Bone
  17. 框架&amp;样式表
  18. Easyui combobox下拉框默认选中第一项
  19. spark streaming插入hbase
  20. SharePoint 2013 Step by Step——使用自定义的List Template

热门文章

  1. 4.3CNN卷积神经网络最详细最容易理解--tensorflow源码MLP对比
  2. 备份schema并排除大表到ASM磁盘上
  3. 向虚拟机注册钩子,实现Bean对象的初始化和销毁方法
  4. JavaScript的介绍概括
  5. 基于C#的多边形冲突检测
  6. Redisson 分布式锁源码 02:看门狗
  7. 飞扬起舞,基于.Net Cli亲手打造.Net Core团队的项目脚手架
  8. Docker入门与进阶(上)
  9. 26、samba搭建
  10. HDU 4445 Crazy Tank 高中物理知识忘得差不多了