JS事件委托(事件代理)
事件委托就是把原本需要绑定在子元素上的事件(onclick、onkeydown 等)委托给它的父元素,让父元素来子元素的冒泡事件,并在子元素发生事件冒泡时找到这个子元素。
举个简单的例子,整个宿舍的同学都需要去取快递,一种方法是让他们一个个去取,另一种方法是把这件事委托给宿舍长,让宿舍长把所有人的快递都取回来,然后再根据收件人一一分发给宿舍的同学。在这里,我们可以将取快递看作一个事件;每个同学看作是需要绑定事件的 DOM 元素;宿舍长看作是这些 DOM 元素的父元素,事件需要绑定在这个父元素上;按照收件人分发快递的过程就是事件执行的过程。
为什么要使用事件委托
在 JavaScript 中,页面内事件处理程序的个数会直接影响页面的整体性能,因为每个事件处理程序都是对象,对象会占用内存,内存中的对象越多,页面的性能则越差。此外,事件处理程序需要与 DOM 节点进行交互,访问 DOM 的次数越多,引起浏览器重绘和重排的次数也就越多,从而影响页面的性能。重绘是指当元素样式改变时,浏览器会根据元素的新样式重新绘制元素的外观。重排是指当 DOM 树的一部分发生变化时(例如元素尺寸改变),浏览器会重新创建 DOM 树。
当页面中很多表格或列表需要添加事件时,如果逐个添加那就太麻烦了,但是使用事件委托就能极大的减轻我们的工作量,同时也能提高页面的性能。事件委托实现原理
事件委托是利用事件的冒泡原理来实现的,大致可以分为三个步骤:确定要添加事件元素的父级元素;
给父元素定义事件,子元素的冒泡事件;
使用 event.target 来定位触发事件冒泡的子元素。
注意:使用事件委托时,并不是说把事件委托给随意一个父元素就行。因为事件冒泡的过程也需要消耗时间,距离越远,所需的时间也就越长,所有最好在直接父元素上使用事件委托。
假如我们要为 ul 列表下的每个 li 标签添加点击事件,如果不使用事件委托,最简单的办法就是使用循环来为每个 li 标签绑定事件,示例代码如下:通过上面的代码可以看出,要为每个 li 标签绑定点击事件,首先需要找到 ul 标签,然后通过 ul 标签找到所有 li 标签, 在通过遍历所有 li 标签来绑定事件。若使用事件委托的话,就会简单很多,示例代码如下:<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JavaScript</title>
</head>
<body>
<ul id="list">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
<script>
window.onload = function(){
var the_ul = document.getElementById('list');
var the_li = the_ul.getElementyTagName('li');
for( var i=0; i < the_li.length; i++ ){
the_li[i].onclick = function(){
console.log(this.innerHTML)
}
}
}
</script>
</body>
</html>
通过代码可以看出,使用事件委托我们只需要为 ul 标签绑定事件,当 li 标签被点击时,由于事件冒泡的特性,会触发 ul 标签上的事件,我们只需要在事件中通过 event 对象中的 target 属性来找到被点击的 li 标签即可。不过这样做也有一个弊端,那就是当我们点击 ul 标签时,也会触发事件。<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JavaScript</title>
</head>
<body>
<ul id="list">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
<script>
window.onload = function(){
var the_ul = document.getElementById('list');
the_ul.onclick = function(e){
console.log(e.target.innerHTML)
}
}
</script>
</body>
</html>
另外,如果我们需要动态的向 ul 标签中添加 li 标签,同时也需要在新添加的 li 标签中添加点击事件,就必须通过事件委托来实现了,示例代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JavaScript</title>
</head>
<body>
<ul id="list" style="width: 100px;margin:0;float: left;">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
<button style="float:left;" id="addli">添加一个 li</button>
<button style="float:left;" id="delli">删除一个 li</button>
<script>
window.onload = function(){
var the_ul = document.getElementById('list');
var the_li = the_ul.getElementyTagName('li');
var sum = the_li.length
the_ul.onclick = function(e){
console.log(e.target.innerHTML)
};
document.getElementById('addli').onclick = function (){
var newli = document.createElement("li");
newli.innerHTML = ++sum;
the_ul.appendChild(newli);
};
document.getElementById('delli').onclick = function (){
the_ul.firstElementChild.remove();
};
}
</script>
</body>
</html>
事件委托的优点
1) 减小内存消耗
使用事件委托可以大量节省内存,减少事件的定义,通过上面的示例可以看出,要为 ul 标签下的所有 li 标签添加点击事件,如果分别为每个 li 标签绑定事件,不仅写起来比较繁琐,而且对内存的消耗也非常大。而使用事件委托的方式将点击事件绑定到 ul 标签上,就可以实现所有 li 标签,简洁、高效。2) 动态绑定事件
在网页中,有时我们需要动态增加或移除页面中的元素,比如上面示例中动态的在 ul 标签中添加 li 标签,如果不使用事件委托,则需要手动为新增的元素绑定事件,同时为删除的元素解绑事件。而使用事件委托就没有这么麻烦了,无论是增加还是减少 ul 标签中的 li 标签,即不需要再为新增的元素绑定事件,也不需要为删除的元素解绑事件。所以使用事件委托动态绑定事件可以减少很多重复工作的。
总结
要使用事件委托,需要保证事件能够发生冒泡,适使用事件委托的事件有 click、mousedown、mouseup、keydown、keyup、keypress 等。需要注意的是,虽然 mouseover 和 mouseout 事件也会发生事件冒泡,但处理起来非常麻烦,所以不在 mouseover 和 mouseout 事件中使用事件委托。另外,对于不会发生事件冒泡的事件(例如 load、unload、abort、focus、blur 等),则无法使用事件委托。
- 随机文章
- 风儿(风儿轻轻的吹)
- 儿童教育文章(儿童教育)
- 光遇花手先祖位置(安卓光遇手花先祖)
- 广州4a广告公司(广州4a广告公司创意总监年薪)
- 抖音卡(抖音卡顿怎么解决)
- xboxones(xboxone手柄怎么配对主机)
- 陈武简历
- 帆船比赛(帆船比赛视频)
- 海猫鸣泣之时游戏(海猫鸣泣之时游戏在哪玩)
- 儋州市第二中学(儋州市第二中学录取分数线)
- 鬼泣5攻略(鬼泣5攻略第三关怎么跳)
- 地球日主题(2020年世界地球日主题)
- 和柳亚子(和柳亚子先生于田)
- 冰客(冰客果汁)
- yy魔兽(yy魔兽世界)
- 国外成人游戏(国外成人游戏注册需要visa信用卡)
- 充值卡代理(充值卡代理加盟)
- 拆奶罩
- 郭妮小说(恶魔的法则郭妮小说)
- 杭同(杭同培训中心怎么样)
- 蝙蝠给人类的一封信(蝙蝠给人类的一封信)
- 服饰加盟(服饰加盟店招商)
- 疯狂填字(疯狂填字5)
- 观音普门品(观音普门品念诵全文)
- 哈利波特官网(哈利波特官网在哪里)
- 骇客神条(骇客神条怎么辨别真假)
- 杜星霖(杜星霖图片)
- 查传倜(查传倜个人生活)
- 钢筋等级符号(钢筋等级符号电脑怎么输入)
- 常州天宁寺(常州天宁寺求什么灵验)
