我的回答
document.addEventListener('click', (e) => {
if (e.target) {
// todo...
}
})
参考回答
了解相关概念
1.什么是事件代理?
事件委托或事件代理:就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。
举例:dom需要事件处理程序,我们都会直接给它设置事件处理程序。但是在ul中1000个li全部需要添加事件处理程序,其具有相同的点击事件,那么可以根据for来进行遍历,也可以在ul上来进行添加。在性能的角度上来看,在ul建立事件会减少dom的交互次数,提高性能。
2.事件代理原理
事件委托就是利用事件的冒泡原理来实现的,就是事件从最深的节点开始,然后逐步向上传播事件。
举例:页面上有这么一个节点树,div>ul>li>a;比如给最里面的a加一个click点击事件,那么这个事件就会一层一层的往外执行,执行顺序a>li>ul>div,有这样一个机制,那么我们给最外面的div加点击事件,那么里面的ul、li、a做点击事件的时候,都会冒泡到最外层的div上,所以都会触发,这就是事件委托,委托它们父级代为执行事件
代码实现
1.实现ul中li的事件代理
window.onload=function(){
var oBtn=document.getElementById('btn');
var oUl=document.getElementById('ul1');
var aLi=oUl.getElementsByTagName('li');
var num=4;
//事件委托,添加的子元素也有事件
oUl.onmouseover=function(e){
var e=e||window.event;
var target=e.target||e.srcElement;
if(target.nodeName.toLowerCase()==='li'){
target.style.background="red";
}
};
oUl.onmouseout=function(e){
var e=e||window.event;
var target=e.target||e.srcElement;
if(target.nodeName.toLowerCase()==='li'){
target.style.background="blue"
}
};
//添加新节点
oBtn.onclick=function(){
num++;
var oLi=document.createElement('li');
oLi.innerHTML=111*num;
oUl.appendChild(oLi)
};
}
2.简单封装一个事件代理通用代码
!function(root,doc){
class Delegator(selector){
this.root=document.querySelector(selector);//父级dom
this.delegatorEvents={}//代理元素及事件
//代理逻辑
this.delegator=e=>{
let currentNode=e.target//目标节点
const targetEventList=this.delegatorEvents[e.type];
//如果当前目标节点等于事件目前所在的节点,不再往上冒泡
while(currentNode !== e.currentTarget){
targetEventList.forEach(target=>{
if(currentNode.matches(target.matcher)){
//开始委托并把当前目标节点的event对象传过去
target.callback.call(currentNode,e)
}
})
currentNode=currentNode.parentNode;
}
}
}
//绑定事件 event---绑定事件类型 selector---需要被代理的选择器 fn---触发函数
on(event,selector,fn){
//相同事件只能添加一次,如果存在,则在对应的代理事件里添加
if(!this.delegatorEvents[event]){
this.delegatorEvents[event]=[{
matcher:selector,
callback:fn
}]
this.root.addEventListener(event,this.delegator)
}else{
this.delegatorEvents[event].push({
matcher:seletor,
callback:fn
})
}
return this;
}
// 移除事件
destory(){
Object.keys(this.delegatorEvents).forEach(eventName=>{
this.root.removeEventListener(eventName,this.delegator)
})
}
root.Delegator=Delegator;
}(window,document)