我的回答

  1. document.addEventListener('click', (e) => {
  2. if (e.target) {
  3. // todo...
  4. }
  5. })

参考回答

了解相关概念

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的事件代理

    1. window.onload=function(){
    2. var oBtn=document.getElementById('btn');
    3. var oUl=document.getElementById('ul1');
    4. var aLi=oUl.getElementsByTagName('li');
    5. var num=4;
    6. //事件委托,添加的子元素也有事件
    7. oUl.onmouseover=function(e){
    8. var e=e||window.event;
    9. var target=e.target||e.srcElement;
    10. if(target.nodeName.toLowerCase()==='li'){
    11. target.style.background="red";
    12. }
    13. };
    14. oUl.onmouseout=function(e){
    15. var e=e||window.event;
    16. var target=e.target||e.srcElement;
    17. if(target.nodeName.toLowerCase()==='li'){
    18. target.style.background="blue"
    19. }
    20. };
    21. //添加新节点
    22. oBtn.onclick=function(){
    23. num++;
    24. var oLi=document.createElement('li');
    25. oLi.innerHTML=111*num;
    26. oUl.appendChild(oLi)
    27. };
    28. }
  • 2.简单封装一个事件代理通用代码

    1. !function(root,doc){
    2. class Delegator(selector){
    3. this.root=document.querySelector(selector);//父级dom
    4. this.delegatorEvents={}//代理元素及事件
    5. //代理逻辑
    6. this.delegator=e=>{
    7. let currentNode=e.target//目标节点
    8. const targetEventList=this.delegatorEvents[e.type];
    9. //如果当前目标节点等于事件目前所在的节点,不再往上冒泡
    10. while(currentNode !== e.currentTarget){
    11. targetEventList.forEach(target=>{
    12. if(currentNode.matches(target.matcher)){
    13. //开始委托并把当前目标节点的event对象传过去
    14. target.callback.call(currentNode,e)
    15. }
    16. })
    17. currentNode=currentNode.parentNode;
    18. }
    19. }
    20. }
    21. //绑定事件 event---绑定事件类型 selector---需要被代理的选择器 fn---触发函数
    22. on(event,selector,fn){
    23. //相同事件只能添加一次,如果存在,则在对应的代理事件里添加
    24. if(!this.delegatorEvents[event]){
    25. this.delegatorEvents[event]=[{
    26. matcher:selector,
    27. callback:fn
    28. }]
    29. this.root.addEventListener(event,this.delegator)
    30. }else{
    31. this.delegatorEvents[event].push({
    32. matcher:seletor,
    33. callback:fn
    34. })
    35. }
    36. return this;
    37. }
    38. // 移除事件
    39. destory(){
    40. Object.keys(this.delegatorEvents).forEach(eventName=>{
    41. this.root.removeEventListener(eventName,this.delegator)
    42. })
    43. }
    44. root.Delegator=Delegator;
    45. }(window,document)