委托模式比较简单,我们先来看个垃圾代码,估计你以前也造过:
let ul = document.getElementById('cont')//外部容器
let li = document.getElementsByTagName('li')//列表
for(let i=0;i<li.length;i++){
li[i].onclick = function(){
this.style.backgroundColor = 'grey'
}
}
为啥说这是一摊垃圾呢?
因为for循环将dom对象绑定了n个事件,这些事件的回调函数本身也是对象,会一下子吃掉好多堆内存空间,对性能来说是个很大的问题。
如何解决呢?
很简单,委托父元素。
let ul = document.getElementById('cont')//外部容器
ul.onclick = function (e) {
let tar = e.target
if (tar.nodeName.toLowerCase() === 'li') {
tar.style.backgroundColor = 'grey'
}
}
没错,就是利用利用事件流模型,从事件捕获开始,到触发该事件,然后再到事件冒泡三个阶段,我们可以将子元素的事件委托给更高层面的父元素来绑定执行,这就是体现了委托模式的思想。
下面再看一段垃圾代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>委托模式</title>
</head>
<body>
<div id="cont">
<button id="btn">click</button>
</div>
</body>
</html>
<script>
var btn = document.querySelector('#btn')
btn.onclick = function(){
document.querySelector('#cont').textContent = '替换了按钮'
}
</script>
为什么是垃圾呢?
因为btn按钮被替换掉了,但是对btn绑定的onclick事件并未释放掉,这个回调函数仍然存在于堆内存中,时间久了就会出现内存泄露了。
我们可以用委托模式改造一下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>委托模式</title>
</head>
<body>
<div id="cont">
<button id="btn">click</button>
</div>
</body>
</html>
<script>
var cont = document.querySelector('#cont')
cont.onclick = function(e){
if(e.target.id === 'btn'){
this.textContent = '替换了按钮'
}
}
</script>
网友评论