在进行DOM优化时需要关注的问题有:修改DOM的时候,会引起页面的重排,重绘。因为JS是单线程执行的,那么在重排重绘的过程中可能会阻塞用户的操作。为了更好的用户体验,必须要严格控制这些操作。

一、对象集合 NodeList
当我们调用:getElementsByTagName,getElementsByName,getElementsByClassName的时候,返回的结果是一个NodeList,这个NodeList是实时的。如果你修改对应的html,那么NodeList中也会得到修改。
而且,NodeList的length属性是指访问NodeList的那一刻,其中包含的节点数量。
所以当下面这个代码运行时有可能会导致死循环(这里先不讨论在一个循环里多次调用appendChild方法):
 var divList = document.getElementsByTagName("div");
for( var i = 0; i < divList.length ; i++ ){
var d = document.createElement("div");
document.body.appendChild(d);
console.log(i);
}
因为当i增加的时候,divList.length也一直在以相同的速度增加,所以当文档中原本的<div>的数量 大于等于 1时,i永远不可能等于divList.length。运行代码的时候,你的页面甚至有可能会显示不出这些div,但是你可以通过控制台打印i的值观察其执行的次数。
所以,永远不要写这样的代码,但是你可以像下面这样子写:
 var divList = document.getElementsByTagName("div");
for( var i = 0, len = divList.length ; i < len ; i++ ){
var d = document.createElement("div");
document.body.appendChild(d);
console.log(i);
}
我们还可以通过一些方法将NodeList转换成普通数组,然后在对其进行操作:
var arrayOfNodes = Array.prototype.slice.call(divList,0);
但是这个方法在IE8及IE之前的版本无效,因为IE8之前将NodeList实现为COM对象,如果真的需要大量用到这个NodeList,并且在IE8和IE之前版本中,那么只好遍历了。
 
二、对DOM进行一些样式的修改
当修改元素的CSS属性时,如果涉及到很多CSS属性,那么不妨考虑增加一个CSS class,然后通过改变元素节点的class来实现这个目的。
修改前:
 element.style.cssText += "width:200px;height:200px;background-color:red;border:1px solid white";
修改后:
在css文件中增加一个样式:
 .active{
width:200px;
height:200px;
background-color:red;
border:1px solid white;
}
在JS中这样写:
 element.className += " active"
 
三、节点增加、移除
比如在一个文档中有一些比较复杂的DOM树需要进行大量的渲染操作,那我们可以先设置其隐藏,让其脱离文档流,等到相应的改变做完之后,再将其显示,使其加入到文档流中。这样做的好处是不会在页面上出现“运行一点,渲染一点”的情况,而是“先运行全部”,“再渲染全部”,从而提高了效率。
 
最后对于上面曾提到的:多次调用appendChild方法导致的多次重排,重绘。可以通过:document.createDocumentFragment()解决这个问题:
 var divList = document.getElementsByTagName("div"),
tempFragment = document.createDocumentFragment();
for( var i = 0; i < 100 ; i++ ){
var d = document.createElement("div");
d.className += " active"
tempFragment.appendChild(d);
}
document.body.appendChild(tempFragment);
 

更多内容参考:《高性能JavaScript一书》

最新文章

  1. ZooKeeper1 利用虚拟机搭建自己的ZooKeeper集群
  2. 学习练习 java面向对象存取款查询余额
  3. EF6数据迁移
  4. poj 2112 floyd+Dinic最大流+二分最小值
  5. [置顶] 基于.NET的快速信息化系统开发框架 — RDIFramework.NET — 系统目录
  6. jQuery和AngularJS的区别
  7. 请详细描述(以硬盘启动)Linux系统从打开主机电源到进入登录界面整个过程的流程。
  8. 学习MACD指标
  9. CCNet: Criss-Cross Attention for Semantic Segmentation 里的Criss-Cross Attention计算方法
  10. Koa 学习笔记
  11. java内存分配与垃圾回收
  12. 基于位置的服务——百度地图SDK练习
  13. 一文弄懂神经网络中的反向传播法(Backpropagation algorithm)
  14. 查看linux服务器的配置
  15. [luogu1962]斐波那契数列
  16. react native 中es6语法解析
  17. 第一篇:打造专属开发工具Eclipse篇
  18. yum安装软件报错:curl#6 - &quot;Could not resolve host: mirrorlist.centos.org; Temporary failure in name resolut
  19. Spark ClassNotFoundException $$anonfun$2
  20. part1:7-Linux网络配置

热门文章

  1. C++之路进阶codevs1269(匈牙利游戏)
  2. Android MVP + 泛型,实现了友好VP交互及Activity潜在的内存泄露的优化
  3. NLog路由规则和上下文信息
  4. 诚信的cpm广告联盟该怎么选择
  5. Core 1.0中publishOptions Include的bug
  6. The constructor BASE64Encoder() is not accessible due to restriction on required library
  7. ubuntu16.04.1下的mysql修改默认编码
  8. cocopods 安装与使用
  9. httpd 安装
  10. A ship is always safe at the shore - but that is not what it is built for.