javascript事件委托

先举个现实生活中委托的例子。比如有3个人在同一个公司里,星期天他们得知他们的快递都要来。如果不用委托,意味着这三个人都要去一次楼下,而且要一直等,直到他们的快递来。但是我们知道公司都是有前台的,所以一般快递公司都是把东西直接放到前台,然后由前台打电话让他们来领取。这里的前台服务就是委托。

在比如电商的模式(如淘宝),如果没有淘宝,大家都要一家一家的去看衣服,找衣服,买衣服。但是有了淘宝的这种类似委托模式,我们只需要用手机进入淘宝就可以去找衣服,买衣服。

同样一个道理,一般来说我们如果要监听一个事件,就直接addEventListerner。但我们知道在javascript中,添加到页面上的事件处理程序是直接影响到整个页面的性能。当我们有很多事件要监听时,我们一个个的获取元素并监听就显然不是好的方法啦。具体的弊端有:

首先,每个都是对象,都会占用内存;内存中的对象越多,性能就越差。其次,必须事先指定所有事件处理程序而导致DOM访问次数,会延迟整个页面的交互就绪时间。

这个时候我们就要用到javascript事件委托。


先举个事件委托的例子

1
2
3
4
5
6
<ul id="parent">
<li id="1">trigger event1</li>
<li id="2">trigger event2</li>
<li id="3">trigger event3</li>
<li id="4">trigger event4</li>
</ul>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var obj = document.getElementById("parent");
obj.addEventListener("click",function(event){
var event = event || window.event;
var target = event.target || event.srcElement;

if(target && target.nodeName == "LI"){
switch(target.id){
case '1':
console.log("first event");
break;
case '2':
console.log("second event");
break;
default:
console.log("fifth event");
}
console.log(event.target.id+" was triggered");
}
})

比如在这个例子里,我要对1234个ul添加事件,一般的方法就是addEventListener。但我们通过委托,只声明了一个变量obj,只用了一个事件监听器。方法是我们监听父元素parent。由于事件冒泡机制,当parent监听的事件发生是,获取target对象,然后内部再对target进行处理。


javascript事件委托的优点

1、document对象很快就可以访问,而且可以在页面生命周期的任何时点上为它添加事件处理程序(无需等待DOMContentLoaded或load事件)。换句话说,只要可单击的元素呈现在页面上,就可以立即具备适当的功能。

2、在页面中设置事件处理程序所需的时间更少。只添加一个事件处理程序所需的DOM引用更少,所花的时间也更少。

3、整个页面占用的内存空间更少,能够提升整体性能。


总结事件委托

使用事件委托技术能让你避免对特定的每个节点添加事件监听器;相反,事件监听器是被添加到它们的父元素上。事件监听器会分析从子元素冒泡上来的事件,找到是哪个子元素的事件,并做相应的处理。


回顾事件冒泡和事件捕获(javascript的事件传播过程)

Netscape定义了一种叫做事件捕获的处理方法,事件首先发生在 DOM树的最高层对象(document)然后往最深层的元素传播。如:事件捕获首先发生在document上,然后是html元素,body元 素,最后是button元素。

IE的处理方法正好相反。他们定义了一种叫事件冒泡的方法。事件冒泡认为事件促发的最深层元素首先接收事件。然后是它的父元素,依次向上,知道 document对象最终接收到事件。尽管相对于html元素来说,document没有独立的视觉表现,他仍然是html元素的父元素并且事件能冒泡到 document元素。