本例代码在Github
事件委托简单来说,就是触发事件的DOM元素本身不执行绑定的事件,而是交给父元素或上上级甚至根元素去处理
先看个例子1
2
3
4
5
6
7
8
9
10
11
12<div>
<ul>
<li>AA <span>A1</span> <span>A2</span></li>
<li>BB <span>B1</span> <span>B2</span></li>
<li>CC <span>C1</span> <span>C2</span></li>
</ul>
<ul>
<li>DD <span>D1</span> <span>D2</span></li>
<li>EE <span>E1</span> <span>E2</span></li>
<li>FF <span>F1</span> <span>F2</span></li>
</ul>
</div>
假设这个列表的LI和SPAN均需要加上click事件,常规做法是在每个DOM都绑定事件,比如1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25let liArr = document.getElementsByTagName("li");
for(let i = 0; i < liArr.length; i++){
liArr[i].addEventListener("click",(evt)=>{
console.log("click li");
});
}
let spanArr = document.getElementsByTagName("span");
for(let i = 0; i < spanArr.length; i++){
spanArr[i].addEventListener("click",(evt)=>{
console.log("click span");
evt.stopPropagation();
});
}let liArr = document.getElementsByTagName("li");
for(let i = 0; i < liArr.length; i++){
liArr[i].addEventListener("click",(evt)=>{
console.log("click li");
});
}
let spanArr = document.getElementsByTagName("span");
for(let i = 0; i < spanArr.length; i++){
spanArr[i].addEventListener("click",(evt)=>{
console.log("click span");
evt.stopPropagation();
});
}
这种做法,简单页面还挺适用,遇到DOM元素多的,或者需要有删除增加需求的,就需要不断执行绑定操作,这样一来是会消耗很多内存,二来是容易出错
这时就需要事件委托,把事件绑定在父级元素
浏览器的事件冒泡看这里,Capture和Bubble,简明解读addEventListener的第三个参数
因为LI和SPAN都在DIV里面,所以只需绑定DIV即可1
2
3
4
5
6
7
8document.getElementsByTagName("div")[0].addEventListener("click",(evt)=>{
console.log(evt);
if("span" == evt.target.nodeName.toLocaleLowerCase()){
console.log("is a span", evt.target.innerText);
}else if("li" == evt.target.nodeName.toLocaleLowerCase()){
console.log("is a li", evt.target.innerText);
}
});
在参数即event事件可以找到是哪个DOM触发了事件
看起来跟一般事件一样,多了一个触发元素的判断
为此jQuery从1.4.2新增了delegate函数,但到了1.7版本就换成 on函数,用法是一样的
$.on()
和 $.click()
最大的区别是执行语句之后,新增加的DOM元素,只要符合选择器,也会绑定on函数指定的事件,而click则不会
on的语法,$.on( events [, selector ] [, data ], handler )
选择器用于选择后代元素,所以事件的触发来自于后代元素,而非绑定on的元素
对于本例来说,改成jquery.on也没啥变化
1 | $("div").on("click", "li, span", (evt) => { |