淺談事件代理

一、什麼是事件代理web

意思:代理、委託。事件代理在JS世界中一個很是有用也頗有趣的功能。當咱們須要對不少元素添加事件的時候,能夠經過將事件添加到它們的父節點而將事件委託給父節點來觸發處理函數。數組

二、運用場景緩存

當子元素被頻繁添加或者刪除時,給子元素綁定事件,須要在每次添加或者刪除時從新綁定,這就形成了很是不方便,那麼此時此刻:事件代理,能幫你輕鬆解決這個麻煩的問題。dom

三、下面是我實現的一個簡單的事件代理方法函數

  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學習

關於事件代理還有不少東西能夠深刻學習和研究,但願你們給我支持,多留言,一塊兒討論,共同進步,謝謝!!!spa

相關文章
相關標籤/搜索