文章目錄
  1. 1. 什么是事件委托
  2. 2. 事件委托的原理
  3. 3. 事件委托的优点
  4. 4. 注意
  5. 5. 代码实现
  6. 6. 参考

什么是事件委托

事件委托是把原本需要监听的事件委托给父元素, 让父元素承担监听的任务

事件委托的原理

事件代理用到了两个在JavaSciprt事件中的特性:事件冒泡以及目标元素。

当一个元素上的事件被触发的时候,比如说鼠标点击了一个按钮,同样的事件将会在那个元素的所有祖先元素中被触发。这一过程被称为事件冒泡;这个事件从原始元素开始一直冒泡到DOM树的最上层。任何一个事件的目标元素都是最开始的那个元素,并且它在我们的元素对象中以属性的形式出现。

使用事件代理,我们可以把事件处理器添加到一个元素上,等待一个事件从它的子级元素里冒泡上来,并且可以得知这个事件是从哪个元素开始的

事件委托的优点

  1. 管理的函数变少了。不需要为每个元素都添加监听函数。对于同一个父节点下面类似的子元素,可以通过委托给父元素的监听函数来处理事件。

  2. 可以方便地动态添加和修改元素,不需要因为元素的改动而修改事件绑定。

  3. JavaScript和DOM节点之间的关联变少了,这样也就减少了因循环引用而带来的内存泄漏发生的概率。

注意

  1. 不是所有的事件都能冒泡的。blur、focus、load和unload不能像其它事件一样冒泡。事实上blur和focus可以用事件捕获而非事件冒泡的方法获得(在IE之外的其它浏览器中)。

  2. 在管理鼠标事件的时候有些需要注意的地方。如果你的代码处理mousemove事件的话你遇上性能瓶颈的风险可就大了,因为mousemove事件触发非常频繁。而mouseout则因为其怪异的表现而变得很难用事件代理来管理。

代码实现

简单的事件委托

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
function delegateEvent(interfaceEle, selector, type, fn) {
if(interfaceEle.addEventListener){
interfaceEle.addEventListener(type, eventfn);
}else{
interfaceEle.attachEvent("on"+type, eventfn);
}

function eventfn(e){
var e = e || window.event;
var target = e.target || e.srcElement;
if (matchSelector(target, selector)) {
if(fn) {
fn.call(target, e);
}
}
}
}
/**
* only support #id, tagName, .className
* and it's simple single, no combination
*/
function matchSelector(ele, selector) {
// if use id
if (selector.charAt(0) === "#") {
return ele.id === selector.slice(1);
}
// if use class
if (selector.charAt(0) === ".") {
return (" " + ele.className + " ").indexOf(" " + selector.slice(1) + " ") != -1;
}
// if use tagName
return ele.tagName.toLowerCase() === selector.toLowerCase();
}
//调用
var odiv = document.getElementById("oDiv");
delegateEvent(odiv,"a","click",function(){
alert("1");
})

参考

JavaScript的事件代理
事件模型及事件代理/委托

文章目錄
  1. 1. 什么是事件委托
  2. 2. 事件委托的原理
  3. 3. 事件委托的优点
  4. 4. 注意
  5. 5. 代码实现
  6. 6. 参考