秒懂JS事件委托,不再迷惑
「这是我参与11月更文挑战的第26天,活动详情查看:2021最后一次更文挑战」
本节我们主要说的是事件委托,也称事件代理,它是对事件冒泡的一个应用,什么是事件委托呢?
首先我们需要知道:在 JavaScript 中,添加到页面上的事件处理程序数量将直接关系到页面的整体运行性能。导致这一问题有多方面的原因。
- 首先,每个函数都是对象,都会占用内存;内存中的对象越多,性能就越差。
- 其次,必须事先指定所有事件处理程序而导致的 DOM 访问次数,会延迟整个页面的交互就绪时间。
前言
???? JavaScript里的事件冒泡
???? JavaScript的事件捕获你知道吗?
实例分析一
我们先来看一个示例:
以下列表中,包含三个被单击后会执行操作的列表项。按照传统的做法,需要像下面这样为它们添加 3 个事件处理程序。如果在一个复杂的 Web 应用程序中,对所有可单击的元素都采用这种方式,那么结果就会有数不清的代码用于添加事件处理程序。
所以为了解决这种问题,我们有一个解决方案,就是【事件委托】。事件委托利用了事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。
简单的说就是,当元素的事件触发时,把要做的事情委托给父元素来处理
现在我们利用事件委托来修改以上的代码,可以这样写
<ul id="myLinks">
<li id="goSomewhere">Go somewhere</li>
<li id="doSomething">Do something</li>
<li id="sayHi">Say hi</li>
</ul>
var list = document.getElementById("myLinks");
EventUtil.addHandler(list, "click", function(event){
event = EventUtil.getEvent(event);
var target = EventUtil.getTarget(event);
switch(target.id){
case "doSomething":
document.title = "I changed the document's title";
break;
case "goSomewhere":
location.href = "http://www.wrox.com";
break;
case "sayHi":
alert("hi");
break;
}
});
代码分析:
在这段代码中,我们使用事件委托只为<ul>
元素添加了一个 onclick
事件处理程序。由于所有列表项都是这个元素的子节点,而且它们的事件会冒泡,所以单击事件最终会被这个函数处理。
然后我们利用id
来判断对应的列表项需要执行的操作,这样只添加了一个事件处理程序,就实现了和前面一样的效果,并且这段代码的消耗更低,占用内存更少。
实例分析二
事件委托还有其他的用途,比如你有一堆的菜单按钮,根据传统的做法,根据不同的需求,我们需要给每个按钮添加一个onclick
但是有了事件委托你可以这样做,首先为有方法调用的按钮添加 data-action
特性(attribute)
<div id="menu">
<button data-action="edit">编辑</button>
<button data-action="load">加载</button>
<button data-action="search">搜索</button>
</div>
然后为为整个菜单添加一个处理程序,处理程序读取特性(attribute)并执行该方法。
class Menu {
constructor(elem) {
this._elem = elem;
// 给this.onClick绑定 this,否则内部的 this 将引用 DOM 元素(elem),而不是 Menu 对象
elem.onclick = this.onClick.bind(this);
}
edit() {console.log('编辑')}
load() {console.log('加载')}
search() {console.log('搜索')}
onClick(event) {
let action = event.target.dataset.action;
if (action) {
this[action]();
}
};
}
new Menu(menu);
什么时候用事件委托?
适用的情况:
- 所有用到按钮的事件(多数鼠标事件和键盘事件)都适合采用事件委托技术,如
click,mousedown,mouseup,keydown,keyup,keypress。
等。
不适用的情况:
-
focus,blur
之类的,本身就没用冒泡的特性,所以不能用事件委托。 -
mouseover、mouseout
虽然也有事件冒泡,但是处理它们的时候需要特别的注意,因为需要经常计算它们的位置,处理起来不太容易。
参考资料:
《Javascript高级程序设计》
Event delegation
????【点赞】【关注】不迷路,更多前端干货等你解锁
往期推荐
???? 一起来看看JS的原型继承
???? JS中的getter和setter你会用吗?
???? 深入理解ES6箭头对象
???? JS的装饰器模式实例分析