一、什麼是事件代理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