摘要:概念事件委托,通俗來(lái)說(shuō)就是將元素的事件委托給它的父級(jí)或者更外級(jí)元素處理。級(jí)事件規(guī)定的事件流包括三個(gè)階段事件捕獲目標(biāo)階段事件冒泡原理事件委托就是利用事件冒泡機(jī)制實(shí)現(xiàn)的。最適合采用事件委托技術(shù)的事件包括和。
概念
事件委托,通俗來(lái)說(shuō)就是將元素的事件委托給它的父級(jí)或者更外級(jí)元素處理。
事件流事件流描述的是從頁(yè)面中接收事件的順序。
事件冒泡:事件開(kāi)始由最具體的元素接收,然后逐級(jí)向上傳播到較為不具體的節(jié)點(diǎn)(或文檔)。
事件捕獲:事件開(kāi)始由不太具體的節(jié)點(diǎn)接收,然后逐級(jí)向下傳播到最具體的節(jié)點(diǎn)。它與事件冒泡是個(gè)相反的過(guò)程。
DOM2級(jí)事件規(guī)定的事件流包括三個(gè)階段:
事件捕獲
目標(biāo)階段
事件冒泡
原理事件委托就是利用事件冒泡機(jī)制實(shí)現(xiàn)的。
假設(shè)有一個(gè)列表,要求點(diǎn)擊列表項(xiàng)彈出對(duì)應(yīng)字段。
不使用事件委托
var myLink = document.getElementById("myLink"); var li = myLink.getElementsByTagName("li"); for(var i = 0; i < li.length; i++) { li[i].onclick = function(e) { var e = event || window.event; var target = e.target || e.srcElement; alert(e.target.id + ":" + e.target.innerText); }; }
這樣做存在的問(wèn)題:
給每個(gè)列表項(xiàng)都綁定事件,消耗內(nèi)存
當(dāng)有動(dòng)態(tài)添加的元素時(shí),需要重新給元素綁定事件
使用事件委托
var myLink = document.getElementById("myLink"); myLink.onclick = function(e) { var e = event || window.event; var target = e.target || e.srcElement; if(e.target.nodeName.toLowerCase() == "li") { alert(e.target.id + ":" + e.target.innerText); } };
上述代碼是將事件委托給列表項(xiàng)的父級(jí),通過(guò) target 下的 nodeName 屬性作出判斷。
也可以給每個(gè)列表項(xiàng)綁定與其對(duì)應(yīng)的事件。如:
var myLink = document.getElementById("myLink"); myLink.onclick = function(e) { var e = event || window.event; var target = e.target || e.srcElement; switch(target.id) { case "1": target.style.backgroundColor = "red"; break; case "2": alert("這是第二項(xiàng)"); break; case "3": alert(e.target.id + ":" + e.target.innerText); break; default: alert("..."); } };
上述代碼是通過(guò)判斷 target 下的 id 屬性,執(zhí)行不同的事件。
事件委托的優(yōu)點(diǎn):
只需要將同類(lèi)元素的事件委托給父級(jí)或者更外級(jí)的元素,不需要給所有元素都綁定事件,減少內(nèi)存空間占用,提升性能
動(dòng)態(tài)新增的元素?zé)o需重新綁定事件
需要注意的地方:
事件委托的實(shí)現(xiàn)依靠事件冒泡,因此不支持事件冒泡的事件就不適合用事件委托。
最適合采用事件委托技術(shù)的事件包括 click、mousedown、mouseup、keydown、keyup 和 keypress。雖然 mouseover 和 mouseout 事件也冒泡,但要適當(dāng)處理它們并不容易,而且經(jīng)常需要計(jì)算元素的位置。(因?yàn)楫?dāng)鼠標(biāo)從一個(gè)元素移到其子節(jié)點(diǎn)時(shí),或者當(dāng)鼠標(biāo)移出該元素時(shí),都會(huì)觸發(fā) mouseout 事件。)
不是所有的事件綁定都適合使用事件委托,不恰當(dāng)使用反而可能會(huì)導(dǎo)致不需要綁定事件的元素也被綁定上了事件。
Jquery中的事件委托jquery中實(shí)現(xiàn)事件委托的幾種方法:
on
on(events, [selector], [data], fn)
// 將 li 的事件委托給它的父元素 $("#myLink").on("click", "li", function() { // todo... });
live
該方法在 jquery 1.7 版本已被廢棄。
delegate
delegate(selector, [type], [data], fn)
$("#myLink").delegate("li", "click", function() { // todo... });
該方法在 jquery 3.0 版本已被廢棄。用 on() 代替。
在 jquery 中, delegate() 、live() 、 one() 、bind()等最終都是依賴(lài) on() 方法實(shí)現(xiàn)的。因此可以直接使用 on() 替代其他方法。
封裝一個(gè)事件委托方法需要注意的地方:
保證兼容性,包括:事件綁定、元素選擇器 Element.matches 、事件 event 對(duì)象
回調(diào)函數(shù) this 指向
上面的示例中,當(dāng)目標(biāo)元素下還有子元素時(shí),子元素不能觸發(fā)事件。解決辦法是在觸發(fā)過(guò)程中對(duì)元素進(jìn)行判斷,如果當(dāng)前觸發(fā)的元素不是目標(biāo)元素,就繼續(xù)往該元素的 parentNode 查找,否則循環(huán)結(jié)束。
/** * [delegateEvent description] * @param {[type]} parentSelector 父元素 * @param {[type]} targetSelector 目標(biāo)元素 * @param {[type]} events 事件 * @param {Function} fn 回調(diào)函數(shù) * @return {[type]} null */ function delegateEvent(parentSelector, targetSelector, events, fn) { // 事件綁定兼容性處理 function addEvent(ele, type, handle) { if(ele.addEventListener) { ele.addEventListener(type, handle, false); } else if(ele.attachEvent){ ele.attachEvent("on" + type, handle); } else { ele["on" + type] = handle; } } // 如果元素被指定的選擇器字符串選擇,Element.matches() 方法返回 true; 否則返回 false。 // 對(duì)于不支持 Element.matches() 或 Element.matchesSelector(),但支持 document.querySelectorAll() 方法的瀏覽器,存在以下替代方案 if (!Element.prototype.matches) { Element.prototype.matches = Element.prototype.matchesSelector || Element.prototype.mozMatchesSelector || Element.prototype.msMatchesSelector || Element.prototype.oMatchesSelector || Element.prototype.webkitMatchesSelector || function(s) { var matches = (this.document || this.ownerDocument).querySelectorAll(s), i = matches.length; while (--i >= 0 && matches.item(i) !== this) {} return i > -1; }; } // 事件處理邏輯 addEvent(parentSelector, events, function(e) { // 兼容性處理 var e = e || window.event; var t = e.target || e.srcElement; // currentTarget === parentSelector var currentTarget = e.currentTarget; // 遍歷并判斷是否為目標(biāo)元素,如果不是,則往元素的 parentNode 繼續(xù)查找 while(!t.matches(targetSelector)) { // 如果是目標(biāo)元素則跳出循環(huán) if(t === currentTarget) { t = null; break; } t = t.parentNode; } if(t) { // 將回調(diào)函數(shù)的 this 指向目標(biāo)元素 fn.call(t, Array.prototype.slice.call(arguments)); } }); }
調(diào)用示例:
var myLink = document.querySelector("#myLink"); delegateEvent(myLink, "li.link", "click", function() { console.log(this, this.id + ":" + this.innerText); });
原文地址:https://github.com/daijingfeng/blog/issues/1
參考資料:
1、《JavaScript高級(jí)程序設(shè)計(jì)(第3版)》
2、Element.matches() API https://developer.mozilla.org...
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/90226.html
摘要:前言之前不太明白事件委托??戳诉@個(gè)帖子,跟著代碼操作了一遍,終于明白了事件委托。推薦理由一步一步,漸進(jìn)式分析來(lái)說(shuō)明事件委托。為簽收快遞,有兩種辦法一是三個(gè)人在公司門(mén)口等快遞二是委托給前臺(tái)代為簽收。 前言:之前不太明白事件委托。 看了這個(gè)帖子,跟著代碼操作了一遍,終于明白了事件委托。所以轉(zhuǎn)載。 推薦理由:一步一步,漸進(jìn)式分析來(lái)說(shuō)明事件委托。 什么叫事件委托呢?它還有一個(gè)名字叫事件代理 ...
摘要:當(dāng)初學(xué)時(shí),學(xué)到委托概念的時(shí)候,有點(diǎn)不知所措,在工作后運(yùn)用了很多后才發(fā)現(xiàn)真的好用。事件的冒泡,所以才可以在父元素來(lái)監(jiān)聽(tīng)子元素觸發(fā)的事件。事件的冒泡這個(gè)要講一下,在的時(shí)候我們可以設(shè)置事件模型事件冒泡事件捕獲,一般來(lái)說(shuō)都是用事件冒泡的模型。 當(dāng)初學(xué)C#時(shí),學(xué)到委托概念的時(shí)候,有點(diǎn)不知所措,在工作后運(yùn)用了很多后才發(fā)現(xiàn)真的好用。在JavaScript里面也有事件委托的概念,那在JavaScrip...
摘要:當(dāng)初學(xué)時(shí),學(xué)到委托概念的時(shí)候,有點(diǎn)不知所措,在工作后運(yùn)用了很多后才發(fā)現(xiàn)真的好用。事件的冒泡,所以才可以在父元素來(lái)監(jiān)聽(tīng)子元素觸發(fā)的事件。事件的冒泡這個(gè)要講一下,在的時(shí)候我們可以設(shè)置事件模型事件冒泡事件捕獲,一般來(lái)說(shuō)都是用事件冒泡的模型。 當(dāng)初學(xué)C#時(shí),學(xué)到委托概念的時(shí)候,有點(diǎn)不知所措,在工作后運(yùn)用了很多后才發(fā)現(xiàn)真的好用。在JavaScript里面也有事件委托的概念,那在JavaScrip...
摘要:說(shuō)明這篇文章說(shuō)中的事件委托,這次先說(shuō)一些比較基本的知識(shí)。第一段綁定了兩次事件,第二段綁定了一次事件也就是說(shuō),原來(lái)在上綁定的事件,現(xiàn)在委托在了父元素上,而在上只需要綁定一次就可以了。我們用事件委托的方式,再來(lái)改改。 說(shuō)明 這篇文章說(shuō)JavaScript中的事件委托,這次先說(shuō)一些比較基本的知識(shí)。 事件委托 是什么 先來(lái)看看事件委托的概念 事件委托就是利用事件冒泡,只指定一個(gè)事件處理程序,就...
閱讀 2558·2021-10-12 10:12
閱讀 1738·2019-08-30 15:52
閱讀 2479·2019-08-30 13:04
閱讀 1759·2019-08-29 18:33
閱讀 987·2019-08-29 16:28
閱讀 475·2019-08-29 12:33
閱讀 2076·2019-08-26 13:33
閱讀 2380·2019-08-26 11:36