基本概念
事件代理(Event Delegation),又称之为事件委托。是JavaScript中常用绑定事件的常用技巧。顾名思义,“事件代理”即是把原本需要绑定在子元素的响应事件(click、keydown......)委托给父元素,让父元素担当事件监听的职务。事件代理的原理是DOM元素的事件冒泡。
事件委托的优点:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>事件绑定</title>
<script src="../../src/event-bind/index.js"></script>
</head>
<body>
<ul id='items'>
<li>AAAA</li>
<li>BBBB</li>
<li>CCCC</li>
<li>DDDD</li>
<div>EEEE</div>
</ul>
<script>
//调用函数绑定事件
addEventListener('#items', 'click', function(e){
//输出标签文本
console.log(this.innerHTML);
}, 'li');
</script>
</body>
</html>
如上面代码所示,如果给每个li列表项都绑定一个函数,那对内存的消耗是非常大的,因此较好的解决办法就是将li元素的点击事件绑定到它的父元素ul身上,执行事件的时候再去匹配判断目标元素。
export function addEventListener(el, type, fn, selector){
//判断 el 的类型
if(typeof el === 'string'){
el = document.querySelector(el);
}
//事件绑定
//若没有传递子元素的选择器, 则给 el 元素绑定事件
if(!selector){
el.addEventListener(type, fn);
}else{
el.addEventListener(type, function(e){
//获取点击的目标事件源
const target = e.target;
//判断选择器与目标元素是否相符合
if(target.matches(selector)){
//若符合 则调用回调
fn.call(target, e);
}
});
}
}
下面是原生写法主要看上面的封装函数处理事件委托:
<ul id="myLinks">
<li id="go1">1</li>
<li id="do2">2</li>
<li id="sayHi">Say hi</li>
</ul>
var item1 = document.getElementById("go1");
var item2 = document.getElementById("do2");
var item3 = document.getElementById("sayHi");
item1.onclick = function() {
location.href = "http://www.baidu.com";
};
item2.onclick = function() {
document.title = "事件委托";
};
item3.onclick = function() {
alert("hi");
};
如果在一个复杂的 Web 应用程序中,对所有可单击的元素都采用这种方式,那么结果就会有数不 清的代码用于添加事件处理程序。此时,可以利用事件委托技术解决这个问题。使用事件委托,只需在 DOM 树中尽量最高的层次上添加一个事件处理程序,如下面的例子所示
var item1 = document.getElementById("goSomewhere");
var item2 = document.getElementById("doSomething");
var item3 = document.getElementById("sayHi");
document.addEventListener("click", function (event) {
var target = event.target;
switch (target.id) {
case "doSomething":
document.title = "事件委托";
break;
case "goSomewhere":
location.href = "http://www.baidu.com";
break;
case "sayHi": alert("hi");
break;
}
})