• 浅谈事件代理


    1、什么是事件代理

    意思:代理、委托。事件代理在JS世界中一个非常有用也很有趣的功能。当我们需要对很多元素添加事件的时候,可以通过将事件添加到它们的父节点而将事件委托给父节点来触发处理函数。

    2、运用场景

    当子元素被频繁添加或者删除时,给子元素绑定事件,需要在每次添加或者删除时重新绑定,这就造成了非常不方便,那么此时此刻:事件代理,能帮你轻松解决这个麻烦的问题。

    3、下面是我实现的一个简单的事件代理方法

      1 window.DELEGATE = {};//命名空间
      2     /**
      3      * 事件处理对象
      4      * @type {{addHandler: addHandler, removeHandler: removeHandler}}
      5      */
      6     window.DELEGATE.EventUtil = {
      7         addHandler: function (element, type, handler) {
      8             if (element.addEventListener) {
      9                 element.addEventListener(type, handler, false);
     10             } else if (element.attachEvent) {
     11                 element.attachEvent("on" + type, handler);
     12             } else {
     13                 element["on" + type] = handler;
     14             }
     15         },
     16         removeHandler: function(element, type, handler){
     17             if (element.removeEventListener){
     18                 element.removeEventListener(type, handler, false);
     19             } else if (element.detachEvent){
     20                 element.detachEvent("on" + type, handler);
     21             } else {
     22                 element["on" + type] = null;
     23             }
     24         }
     25     };
     26     /**
     27      * 比较当前选择于目标函数是否相等
     28      * @param element 当前元素
     29      * @param selector 目标元素标识
     30      */
     31     window.DELEGATE.matchesSelector = function(element, selector){
     32         if(element.matches){
     33             return element.matches(selector);
     34         } else if(element.matchesSelector){
     35             return element.matchesSelector(selector);
     36         } else if(element.webkitMatchesSelector){
     37             return element.webkitMatchesSelector(selector);
     38         } else if(element.msMatchesSelector){
     39             return element.msMatchesSelector(selector);
     40         } else if(element.mozMatchesSelector){
     41             return element.mozMatchesSelector(selector);
     42         } else if(element.oMatchesSelector){
     43             return element.oMatchesSelector(selector);
     44         } else if(element.querySelectorAll){
     45             var matches = (element.document || element.ownerDocument).querySelectorAll(selector),
     46                 i = 0;
     47             while(matches[i] && matches[i] !== element) i++;
     48             return matches[i] ? true: false;
     49         }
     50         throw new Error('Your browser version is too old,please upgrade your browser');
     51     };
     52 
     53     /**
     54      * 缓存所有事件,以数组形式缓存(一个dom上绑定了多个事件时),
     55      * 缓存例子为agentObj[e.currentTarget的id,无id用temp++值表示][event][触发事件的tag][]
     56      */
     57     window.DELEGATE.agentObj = {};
     58     /**
     59      * 用于缓存所有需要触发事件的dom tag,
     60      * 缓存例子:selectorObj[e.currentTarget的id,无id用temp++值表示][触发事件的tag][]
     61      * 用对象的目的在于方便判断是否已经缓存过了
     62      */
     63     window.DELEGATE.selectorObj = {};
     64     /**
     65      * 用于e.currentTarget没有id的情况,产生id
     66      */
     67     window.DELEGATE.temp = 0;
     68 
     69     /**
     70      *
     71      * @param parent 父节点id或者父节点元素
     72      * @param eventStr 触发事件
     73      * @param childTag 触发事件元素标志
     74      * @param handler 事件句柄
     75      * @constructor
     76      */
     77     window.DELEGATE.Delegate  = function(parent, eventStr, childTag, handler) {
     78         var event = eventStr.toLowerCase(),
     79             parentObj = null;
     80         if (typeof parent == 'object') {
     81             parentObj =
     82                     parent === document || parent === document.body || parent === document.documentElement ?
     83                     document.body :
     84                     parent;
     85             if (parentObj.id) {
     86                 parent = parentObj.id
     87             } else {
     88                 parent = ++window.DELEGATE.temp;
     89             }
     90         } else {
     91             parentObj = document.getElementById(parent);
     92         }
     93 
     94         if (!window.DELEGATE.selectorObj[parent]) {
     95             window.DELEGATE.selectorObj[parent] = {};
     96         }
     97         if (!window.DELEGATE.selectorObj[parent][childTag]) {
     98             window.DELEGATE.selectorObj[parent][childTag] = [];
     99         }
    100         if (!window.DELEGATE.agentObj[parent]) {
    101             window.DELEGATE.agentObj[parent] = {};
    102             window.DELEGATE.EventUtil.addHandler(parentObj, event, function (e) {
    103                 e.stop = false;
    104                 /**
    105                  * 阻止冒泡,重置该方法
    106                  */
    107                 e.stopPropagation = function () {
    108                     e.stop = true;
    109                 };
    110                 var parentElement = e.target;
    111                 while (parentElement != e.currentTarget && !e.stop) {//从子节点向上冒泡遍历每一个节点与目标节点比较,一直到父节点停止
    112                     for (var selector in window.DELEGATE.selectorObj[parent]) {
    113                         if (window.DELEGATE.matchesSelector(parentElement, selector)) {
    114                             for (var agent in window.DELEGATE.agentObj[parent][eventStr][selector]) {
    115                                 window.DELEGATE.agentObj[parent][eventStr][selector][agent].call(parentElement, e);
    116                             }
    117                         }
    118                     }
    119                     parentElement = parentElement.parentElement || parentElement.parentNode;
    120                 }
    121             });
    122         }
    123         if (!window.DELEGATE.agentObj[parent][eventStr]) {
    124             window.DELEGATE.agentObj[parent][eventStr] = {};
    125         }
    126         if (!window.DELEGATE.agentObj[parent][eventStr][childTag]) {
    127             window.DELEGATE.agentObj[parent][eventStr][childTag] = [];
    128         }
    129         window.DELEGATE.agentObj[parent][eventStr][childTag].push(handler);
    130 
    131     };

    运行demo:http://runjs.cn/detail/iaz5oole

    关于事件代理还有很多东西可以深入学习和研究,希望大家给我支持,多留言,一起讨论,共同进步,谢谢!!!

  • 相关阅读:
    IT名词备忘录——汇编
    逆转链表的实现
    编写安全的代码的一些技巧
    extern c 谈
    回调函数
    职场必备八个黄金句型
    CString类的用法介绍和自己动手写的CString类
    61条面向对象设计的经验原则(转贴)
    sprintf的用法
    VisualStudioVS2010统计代码行数
  • 原文地址:https://www.cnblogs.com/bo-haier/p/5644731.html
Copyright © 2020-2023  润新知