‘手寫 ’ 這個詞 ,面試是不是聽過無數遍呢 ! 今天我們來手寫一個這樣的事件委托函數 =》 function( parent, selector, type , handle) {} 你需要傳遞的參數分別是: parent: 事件綁定的父級 selector: 選擇器, type: 事件類型 ha ...
‘手寫 ’ 這個詞 ,面試是不是聽過無數遍呢 !
今天我們來手寫一個這樣的事件委托函數 =》
function( parent, selector, type , handle) {}
你需要傳遞的參數分別是:
parent: 事件綁定的父級
selector: 選擇器,
type: 事件類型
handle: 事件處理函數
寫之前 先瞭解一下事件委托的概念:
它是通過事件冒泡機制,
即子元素上觸發的事件會冒泡到父級上, 即父級也會觸發該類型的事件,
通過父級觸發的事件拿到事件源對象e.target 就可以 知道 真正觸發事件的元素是什麼。
舉個例子, 一個ul 下麵有 1000 個 li , 我們 要給 li 綁定 點擊事件 , 如果給每個li都綁定一個
點擊事件 會 大量占用 記憶體 , 不利於性能優化, 這種情況下 我們 只需要在ul上綁定一個點擊事件,
通過class 或者 id 來識別每個li , 這樣就大大減少了事件註冊, 而且 再 有新增的li時 我們也無需再去註冊點擊事件
我們來寫個小demo
HTML:
<ul id="parent"> <li>1</li> <li>2</li> <li>3</li> </ul>
css:
.active{ background-color: green; }
js:
const parent = document.getElementById('parent'); function changeColor() {
if (this.classList.contains('active')) {
this.classList.remove('active')
} else {
this.classList.add('active');
}
}
function delegate(parent, selector, type, handle) { }
delegate(parent, 'li', 'click',changeColor);
我們要實現點哪個li , 哪個li就變成原諒色, 再次點擊取消。並 做 瀏覽器的相容
我們開始寫 delegate函數:
function matchSelector(target, selector) { if (selector.match(/^#/g)) { // 匹配以#開頭的字元串 return target.id === selector.slice(1); // 截取#後面的字元串 } if (selector.match(/^\./g)) { // . 要轉義,匹配以點開頭的字元轉 return target.classList.contains(selector.slice(1)) } return target.nodeName.toLowerCase() === selector; // 匹配標簽 } function delegate(parent, selector, type, handle) { if (parent.addEventListener) { parent.addEventListener(type, eventFn, false) } else { // 相容老IE parent.attachEvent('on' + type, handle) } function eventFn(e) { const event = e || window.event; const target = event.target || event.srcElement;// 相容老IE if (matchSelector(target, selector)) { if (handle) { handle.call(target, e); // 讓handle執行時的this指向target } } } }
效果: