一些JavaScript中的DOM的优化小技巧
2024-10-19 01:30:24
在进行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一书》
最新文章
- ZooKeeper1 利用虚拟机搭建自己的ZooKeeper集群
- 学习练习 java面向对象存取款查询余额
- EF6数据迁移
- poj 2112 floyd+Dinic最大流+二分最小值
- [置顶] 基于.NET的快速信息化系统开发框架 — RDIFramework.NET — 系统目录
- jQuery和AngularJS的区别
- 请详细描述(以硬盘启动)Linux系统从打开主机电源到进入登录界面整个过程的流程。
- 学习MACD指标
- CCNet: Criss-Cross Attention for Semantic Segmentation 里的Criss-Cross Attention计算方法
- Koa 学习笔记
- java内存分配与垃圾回收
- 基于位置的服务——百度地图SDK练习
- 一文弄懂神经网络中的反向传播法(Backpropagation algorithm)
- 查看linux服务器的配置
- [luogu1962]斐波那契数列
- react native 中es6语法解析
- 第一篇:打造专属开发工具Eclipse篇
- yum安装软件报错:curl#6 - ";Could not resolve host: mirrorlist.centos.org; Temporary failure in name resolut
- Spark ClassNotFoundException $$anonfun$2
- part1:7-Linux网络配置
热门文章
- C++之路进阶codevs1269(匈牙利游戏)
- Android MVP + 泛型,实现了友好VP交互及Activity潜在的内存泄露的优化
- NLog路由规则和上下文信息
- 诚信的cpm广告联盟该怎么选择
- Core 1.0中publishOptions Include的bug
- The constructor BASE64Encoder() is not accessible due to restriction on required library
- ubuntu16.04.1下的mysql修改默认编码
- cocopods 安装与使用
- httpd 安装
- A ship is always safe at the shore - but that is not what it is built for.