JavaScript事件委托的技術(shù)原理探討示例
如今的JavaScript技術(shù)界里最火熱的一項(xiàng)技術(shù)應(yīng)該是‘事件委托(event delegation)'了。使用事件委托技術(shù)能讓你避免對特定的每個(gè)節(jié)點(diǎn)添加事件監(jiān)聽器;相反,事件監(jiān)聽器是被添加到它們的父元素上。事件監(jiān)聽器會分析從子元素冒泡上來的事件,找到是哪個(gè)子元素的事件?;靖拍罘浅:唵?,但仍有很多人不理解事件委托的工作原理。這里我將要解釋事件委托是如何工作的,并提供幾個(gè)純JavaScript的基本事件委托的例子。
假定我們有一個(gè)UL元素,它有幾個(gè)子元素:
<ul id="parent-list">
<li id="post-1">Item 1</li>
<li id="post-2">Item 2</li>
<li id="post-3">Item 3</li>
<li id="post-4">Item 4</li>
<li id="post-5">Item 5</li>
<li id="post-6">Item 6</li>
</ul>
我們還假設(shè),當(dāng)每個(gè)子元素被點(diǎn)擊時(shí),將會有各自不同的事件發(fā)生。你可以給每個(gè)獨(dú)立的li元素添加事件監(jiān)聽器,但有時(shí)這些li元素可能會被刪除,可能會有新增,監(jiān)聽它們的新增或刪除事件將會是一場噩夢,尤其是當(dāng)你的監(jiān)聽事件的代碼放在應(yīng)用的另一個(gè)地方時(shí)。但是,如果你將監(jiān)聽器安放到它們的父元素上呢?你如何能知道是那個(gè)子元素被點(diǎn)擊了?
簡單:當(dāng)子元素的事件冒泡到父ul元素時(shí),你可以檢查事件對象的target屬性,捕獲真正被點(diǎn)擊的節(jié)點(diǎn)元素的引用。下面是一段很簡單的JavaScript代碼,演示了事件委托的過程:
// 找到父元素,添加監(jiān)聽器...
document.getElementById("parent-list").addEventListener("click",function(e) {
// e.target是被點(diǎn)擊的元素!
// 如果被點(diǎn)擊的是li元素
if(e.target && e.target.nodeName == "LI") {
// 找到目標(biāo),輸出ID!
console.log("List item ",e.target.id.replace("post-")," was clicked!");
}
});
第一步是給父元素添加事件監(jiān)聽器。當(dāng)有事件觸發(fā)監(jiān)聽器時(shí),檢查事件的來源,排除非li子元素事件。如果是一個(gè)li元素,我們就找到了目標(biāo)!如果不是一個(gè)li元素,事件將被忽略。這個(gè)例子非常簡單,UL和li是標(biāo)準(zhǔn)的父子搭配。讓我們試驗(yàn)一些差異比較大的元素搭配。假設(shè)我們有一個(gè)父元素div,里面有很多子元素,但我們關(guān)心的是里面的一個(gè)帶有”classA” CSS類的A標(biāo)記:
// 獲得父元素DIV, 添加監(jiān)聽器...
document.getElementById("myDiv").addEventListener("click",function(e) {
// e.target是被點(diǎn)擊的元素
if(e.target && e.target.nodeName == "A") {
// 獲得CSS類名
var classes = e.target.className.split(" ");
// 搜索匹配!
if(classes) {
// For every CSS class the element has...
for(var x = 0; x < classes.length; x++) {
// If it has the CSS class we want...
if(classes[x] == "classA") {
// Bingo!
console.log("Anchor element clicked!");
// Now do something here....
}
}
}
}
});
上面這個(gè)例子中不僅比較了標(biāo)簽名,而且比較了CSS類名。雖然稍微復(fù)雜了一點(diǎn),但還是很具代表性的。比如,如果某個(gè)A標(biāo)記里有一個(gè)span標(biāo)記,則這個(gè)span將會成為target元素。這個(gè)時(shí)候,我們需要上溯DOM樹結(jié)構(gòu),找到里面是否有一個(gè) A.classA 的元素。
因?yàn)榇蟛糠殖绦騿T都會使用jQuery等工具庫來處理DOM元素和事件,我建議大家都使用里面的事件委托方法,因?yàn)檫@里工具庫里都提供了高級的委托方法和元素甄別方法。
希望這篇文章能幫助你理解JavaScript事件委托的幕后原理,希望你也感受到了事件委托的強(qiáng)大用處!
相關(guān)文章
js自動(dòng)生成的元素與頁面原有元素發(fā)生堆疊的解決方法
js自動(dòng)生成的元素與頁面原有元素發(fā)生堆疊通過去除浮動(dòng),給原有元素(商品擴(kuò)展信息部分)加上clear:both; 果然正常了2013-10-10
js實(shí)現(xiàn)跨域的4種實(shí)用方法原理分析
這篇文章主要分析了js實(shí)現(xiàn)跨域的4種實(shí)用方法原理,主要是使用jsonp跨域,使用window.name來進(jìn)行跨域,對這方面感興趣的朋友可以參考一下2015-10-10
JavaScript實(shí)現(xiàn)帶有子菜單和控件的slider輪播圖效果
本文通過實(shí)例代碼給大家介紹了基于js實(shí)現(xiàn)帶有子菜單和控件的slider輪播圖效果,本文附有圖片和示例代碼,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下吧2017-11-11
javascript 用記憶函數(shù)快速計(jì)算遞歸函數(shù)
摘自《JavaScript: The Good Parts》,作為讀書筆記備用。對于追求執(zhí)行效率的朋友可以參考下。2010-03-03
使用threejs實(shí)現(xiàn)第一人稱視角的移動(dòng)的問題(示例代碼)
第一人稱視角的場景巡檢主要需要解決兩個(gè)問題,人物在場景中的移動(dòng)和碰撞檢測。移動(dòng)與碰撞功能是所有三維場景首先需要解決的基本問題,今天我們就通過最基本的threejs來完成第一人稱視角的場景巡檢功能,感興趣的朋友一起看看吧2022-02-02

