频繁DOM操作问题

      今天看到一篇文章 Nicholas C. Zakas(professional javascript 作者) 的 Speed up your JavaScript, Part 4

,恍然想起以前好像也碰到过上述现象 ,只是没加深究,找到解决方法后就完事大吉了,当时的代码抽象如下:

 

方法1 :

 

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="zh-cn" lang="zh-cn">

<head>
	<title>dom测试</title>
</head>
<body>
	<div>
		<ul id='ul_test'><li>t</li></ul>
	</div>
	
	<script type='text/javascript'>
		window.onload=function () {
			//return;
		setInterval(function(){
			document.getElementById('ul_test').innerHTML='';
			for(var i=0;i<100;i++)  {
				for(var j=0;j<100;j++) {
					var tli=document.createElement('li');
					tli.innerHTML=i+'-'+j;
					document.getElementById('ul_test').appendChild(tli);
				}
			
			}
		},1000);
		
		
		}
	</script>
</body>
</html>


运行时 cpu 暴涨 ,长时间 90以上

 

后来经过多方查看  ,确定了是 多次读写 dom 操作太费cpu ,dom 并没有缓存的操作 ,修改后变为;

 

方法2 :

 

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="zh-cn" lang="zh-cn">

<head>
	<title>dom测试</title>
</head>
<body>
	<div>
		<ul id='ul_test'><li>t2</li></ul>
	</div>
	
	<script type='text/javascript'>
		window.onload=function () {
		
		var ilt=	document.getElementById('ul_test');
		
		setInterval(function(){
			
			
			
			var fragment = [];
			
			for(var i=0;i<100;i++)  {
				for(var j=0;j<100;j++) {
					fragment.push('<li>'+i+'-'+j+'</li>');
				
				}
			
			}
			
			ilt.innerHTML=(fragment.join(''));
			
		},1000);
		
		
		}
	</script>
</body>
</html>
 

 

这样的话 ,cpu 最高在50且就一瞬间,


后看了

JavaScript教程--如何提升JavaScript的运行速度(DOM篇)


又实现了一遍:

 

方法3 :

 

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="zh-cn" lang="zh-cn">

<head>
	<title>dom测试</title>
</head>
<body>
	<div>
		<ul id='ul_test'><li>t2</li></ul>
	</div>
	
	<script type='text/javascript'>
		window.onload=function () {
		
		var ilt=	document.getElementById('ul_test');
		
		setInterval(function(){
			
			ilt.innerHTML='';
			
			var fragment = document.createDocumentFragment();
			
			for(var i=0;i<100;i++)  {
				for(var j=0;j<100;j++) {
					var tli=document.createElement('li');
					tli.appendChild(document.createTextNode(i+'-'+j));
				
					fragment.appendChild(tli);
				}
			
			}
			
			ilt.appendChild(fragment);
			
		},1000);
		
		
		}
	</script>
</body>
</html>

 

方法3 cpu最高 90 ,且也是只有一瞬间 ,比方法1好,但是还有没方法2好 ,

   说明dom操作还是不如 innerHTML 的 ,innerHTML 只有最后加入 ul 的话才需要结构化 ,而dom的话即使采用节点碎片,新create node 也是挺费资源的,fragment用来加快dom操作还是作用很明显的

 

 

避免频繁操作DOM的方法如下: - **批量操作**:将需要对DOM进行的多次操作合并为一次批量操作,减少不必要的重排和重绘。例如,要向一个列表中添加多个元素,先在内存中构建好完整的列表结构,再一次性添加到DOM中。 ```javascript // 创建一个文档片段 const fragment = document.createDocumentFragment(); for (let i = 0; i < 10; i++) { const li = document.createElement('li'); li.textContent = `Item ${i}`; fragment.appendChild(li); } // 一次性将文档片段添加到DOM中 document.getElementById('list').appendChild(fragment); ``` - **缓存查询结果**:避免多次进行相同的DOM查询,将查询结果缓存起来重复使用。例如: ```javascript // 缓存查询结果 const container = document.getElementById('container'); // 多次使用缓存的结果 container.style.color = 'red'; container.textContent = 'New content'; ``` - **使用虚拟DOM**:如果使用的是React、Vue等现代前端框架,它们通常会使用虚拟DOM来最小化实际的DOM操作。虚拟DOM会在内存中创建一个DOM树的副本,并仅在必要时将差异同步到真实的DOM中,从而减少重排和重绘[^4]。 - **CSS优化**:合理使用CSS可以减少DOM操作。例如,使用简单的选择器,避免使用复杂的选择器。 ```css /* 不推荐: 使用复杂的选择器 */ .container > .item + .item { /* 样式规则 */ } /* 推荐: 使用简单的选择器 */ .item { /* 样式规则 */ } ``` - **事件委托**:利用事件冒泡的原理,将事件处理程序绑定到父元素上,而不是每个子元素都绑定事件处理程序,减少DOM事件绑定的数量。例如: ```html <ul id="list"> <li>Item 1</li> <li>Item 2</li> <li>Item 3</li> </ul> ``` ```javascript // 事件委托 document.getElementById('list').addEventListener('click', function(event) { if (event.target.tagName === 'LI') { console.log('Clicked on list item:', event.target.textContent); } }); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值