js的事件代理_事件代理和事件绑定

js的事件代理_事件代理和事件绑定简介由于事件在冒泡阶段向上传播到父节点,因此可以把子节点监听的事件在父节点的监听,由父节点的监听函数统一处理多个子元素的的事件,这种方法就叫做事件的代理,处理如下:varul=document.querySelector('ul');ul.addEventListener('click',function(event){if(event.target.tagName.t...

简介

由于事件在冒泡阶段向上传播到父节点,因此可以把子节点监听的事件在父节点的监听,由父节点的监听函数统一处理多个子元素的的事件,这种方法就叫做事件的代理,处理如下:

var ul = document.querySelector('ul');

ul.addEventListener('click', function (event) { 
   
  if (event.target.tagName.toLowerCase() === 'li') { 
   
    // some code
  }
});
只听到从架构师办公室传来架构君的声音:
螽斯羽,薨薨兮。有谁来对上联或下联?

这样做的好处:

只需在父节点定义一个监听函数,就可以统一处理子节点的事件了;
动态添加子节点,也可以监听到;

下面呢?我们就手动实现下事件代理

实现步骤

创建一个Delegator类,定义一个on方法(监听),再定义一个destroy方式(用于注销事件)

此代码由Java架构师必看网-架构君整理
!function (root, doc) { class Delegator { /* *@param 顶级选择器(代理者) */ constructor (selector) { } /* *绑定事件 *@param event 绑定事件类型 *@param selector 需要被代理的选择器 *@param fn 触发函数 * */ on (event, selector, fn) { } /* *移除事件 */ destroy () { } } root.Delegator = Delegator }(window, document)

定义两个实例属性,分别用来接受root节点和被代理的元素对象。

 constructor (selector) { 
   
      this.root = document.querySelector(selector);//顶级dom
      this.delegatorEvents = { 
   //代理元素及事件
      	//evenType:[{ 
   
			//matcher:selector,//元素dom节点
			//callback:fn,//事件函数
	    }]
	  };
    }

绑定事件具体逻辑

1.事件代理触发顺序满足冒泡规则;;
2.this 应当指向正确的元素;
3.相同事件只做一个监听
4.新添加元素也能够响应绑定;

此代码由Java架构师必看网-架构君整理
constructor (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对象传过去,改为this指向 target.callback.call(currentNode, e); } }) currentNode = currentNode.parentNode; } } } /* *绑定事件 *@param event 绑定事件类型 *@param selector 需要被代理的选择器 *@param 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: selector, callback: fn }) } return this; }

注销事件

    /* *移除事件 */
    destroy () { 
   
      Object.keys(this.delegatorEvents).forEach(eventName => { 
   
        this.root.removeEventListener(eventName, this.delegator)
      });
    }

全部代码

!function (root, doc) { 
   

  class Delegator { 
   
    /* *@param 顶级选择器(代理者) */
    constructor (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;
        }
      }
    }
    /* *绑定事件 *@param event 绑定事件类型 *@param selector 需要被代理的选择器 *@param 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: selector,
          callback: fn
        })
      }
      return this;
    }
    /* *移除事件 */
    destroy () { 
   
      Object.keys(this.delegatorEvents).forEach(eventName => { 
   
        this.root.removeEventListener(eventName, this.delegator)
      });
    }
  }

  root.Delegator = Delegator
}(window, document)
架构君码字不易,如需转载,请注明出处:https://javajgs.com/archives/166230
0
 

发表评论