javascript
JavaScript事件代理和委托
2019獨(dú)角獸企業(yè)重金招聘Python工程師標(biāo)準(zhǔn)>>>
瀏覽器的事件冒泡
當(dāng)事件發(fā)生后,這個(gè)事件就要開(kāi)始傳播。例如我們點(diǎn)擊一個(gè)按鈕時(shí),就會(huì)產(chǎn)生一個(gè)click事件,但這個(gè)按鈕本身不能處理這個(gè)事件,事件必須從這個(gè)按鈕傳播出去,從而到達(dá)能夠處理這個(gè)事件的代碼中。從里到外,直至它被處理,或者它到達(dá)了對(duì)象層次的最頂層,即document對(duì)象(有些瀏覽器是window)
(1)冒泡型事件:事件按照從最特定的事件目標(biāo)到最不特定的事件目標(biāo)(document對(duì)象)的順序觸發(fā)。
? IE 5.5: div -> body -> document
? IE 6.0: div -> body -> html -> document
? Mozilla 1.0: div -> body -> html -> document -> window
(2)捕獲型事件(event capturing):事件從最不精確的對(duì)象(document 對(duì)象)開(kāi)始觸發(fā),然后到最精確的對(duì)象
(3)DOM事件流:同時(shí)支持兩種事件模型:捕獲型事件和冒泡型事件,但是,捕獲型事件先發(fā)生。兩種事件流會(huì)觸及DOM中的所有對(duì)象,從document對(duì)象開(kāi)始,也在document對(duì)象結(jié)束。
DOM2.0模型將事件處理流程分為三個(gè)階段:一、事件捕獲階段,二、事件目標(biāo)階段,三、事件起泡階段。如圖:
事件捕獲:當(dāng)某個(gè)元素觸發(fā)某個(gè)事件(如onclick),頂層對(duì)象document就會(huì)發(fā)出一個(gè)事件流,隨著DOM樹(shù)的節(jié)點(diǎn)向目標(biāo)元素節(jié)點(diǎn)流去,直到到達(dá)事件真正發(fā)生的目標(biāo)元素。在這個(gè)過(guò)程中,事件相應(yīng)的監(jiān)聽(tīng)函數(shù)是不會(huì)被觸發(fā)的。
事件目標(biāo):當(dāng)?shù)竭_(dá)目標(biāo)元素之后,執(zhí)行目標(biāo)元素該事件相應(yīng)的處理函數(shù)。如果沒(méi)有綁定監(jiān)聽(tīng)函數(shù),那就不執(zhí)行。
事件起泡:從目標(biāo)元素開(kāi)始,往頂層元素傳播。途中如果有節(jié)點(diǎn)綁定了相應(yīng)的事件處理函數(shù),這些函數(shù)都會(huì)被一次觸發(fā)。如果想阻止事件起泡,可以使用e.stopPropagation()(Firefox)或者e.cancelBubble=true(IE)來(lái)組織事件的冒泡傳播。
每個(gè) event 都有一個(gè)event.bubbles屬性,可以知道它可否冒泡。
JS事件代理
對(duì)于需要給很多列表式元素添加事件時(shí),可以直接將事件添加到它們的父節(jié)點(diǎn),將事件委托給父節(jié)點(diǎn)來(lái)觸發(fā)處理函數(shù)。利用瀏覽器的事件冒泡機(jī)制實(shí)現(xiàn)單個(gè)元素事件處理
假設(shè)有一個(gè)ul?的父節(jié)點(diǎn)包含一些列l(wèi)i的子節(jié)點(diǎn),希望實(shí)現(xiàn)的效果是:鼠標(biāo)移到li上時(shí)彈出懸浮窗,即li需要出發(fā)處理事件,通常寫(xiě)法是給每個(gè)li綁定onclick等監(jiān)聽(tīng)事件。
//html: <ul id="parent"><li id="child1">Item 1</li><li id="child2">Item 2</li><li id="child3">Item 3</li><li id="child4">Item 4</li><li id="child5">Item 5</li> </ul>js代碼:
//js: function addListeners(li_child){li_child = function clickHandler(){...}; }window.onload = function(){var ul_parent = document.getElementById("parent");var li_childs = ulNode.getElementByTagName("li");for(var i=0, l = li_childs; i < l; i++){addListener(li_childs[i]);} }如果這個(gè)ul中的li子元素會(huì)頻繁地添加或者刪除,我們就需要在每次添加li的時(shí)候都調(diào)用這個(gè)addListener方法來(lái)為每個(gè)li節(jié)點(diǎn)添加事件處理函數(shù)。這就添加的復(fù)雜度和出錯(cuò)的可能性。
更簡(jiǎn)單的方法是使用事件代理機(jī)制,當(dāng)事件被拋到更上層的父節(jié)點(diǎn)的時(shí)候,我們通過(guò)檢查事件的目標(biāo)對(duì)象(target)來(lái)判斷并獲取事件源Li。下面的代碼可以完成我們想要的效果:
// 獲取父節(jié)點(diǎn),并為它添加一個(gè)click事件 document.getElementById("parent").addEventListener("click",function(e) {// 檢查事件源e.targe是否為L(zhǎng)iif(e.target && e.target.nodeName.toUpperCase == "li") {// 真正的處理過(guò)程在這里...} });為父節(jié)點(diǎn)添加一個(gè)click事件,當(dāng)子節(jié)點(diǎn)被點(diǎn)擊的時(shí)候,click事件會(huì)從子節(jié)點(diǎn)開(kāi)始向上冒泡。父節(jié)點(diǎn)捕獲到事件之后,通過(guò)判斷e.target.nodeName來(lái)判斷是否為我們需要處理的節(jié)點(diǎn)。并且通過(guò)e.target拿到了被點(diǎn)擊的Li節(jié)點(diǎn)。從而可以獲取到相應(yīng)的信息,并作處理。
jQuery中delegate函數(shù)
delegate() 方法為指定的元素(屬于被選元素的子元素)添加一個(gè)或多個(gè)事件處理程序,并規(guī)定當(dāng)這些事件發(fā)生時(shí)運(yùn)行的函數(shù),使用 delegate() 方法的事件處理程序適用于當(dāng)前或未來(lái)的元素(比如由腳本創(chuàng)建的新元素)。
$("#parent").delegate("li", "click", function(){// "$(this)" is the node that was clicked... });jQuery的delegate的方法需要三個(gè)參數(shù),一個(gè)選擇器,一個(gè)時(shí)間名稱,和事件處理函數(shù)。
優(yōu)點(diǎn)
通過(guò)上面的介紹,大家應(yīng)該能夠體會(huì)到使用事件委托對(duì)于web應(yīng)用程序帶來(lái)的幾個(gè)優(yōu)點(diǎn):
1.管理的函數(shù)變少了。不需要為每個(gè)元素都添加監(jiān)聽(tīng)函數(shù)。對(duì)于同一個(gè)父節(jié)點(diǎn)下面類似的子元素,可以通過(guò)委托給父元素的監(jiān)聽(tīng)函數(shù)來(lái)處理事件。
2.可以方便地動(dòng)態(tài)添加和修改元素,不需要因?yàn)樵氐母膭?dòng)而修改事件綁定。
3.JavaScript和DOM節(jié)點(diǎn)之間的關(guān)聯(lián)變少了,這樣也就減少了因循環(huán)引用而帶來(lái)的內(nèi)存泄漏發(fā)生的概率。
jquery中對(duì)冒泡和默認(rèn)行為的阻止方法
網(wǎng)頁(yè)中的某些元素是有自己的默認(rèn)行為的,比如果超鏈接單擊后需要跳轉(zhuǎn),提交按鈕點(diǎn)擊后需要提交表單,有時(shí)需要阻止這些行為,也就是默認(rèn)行為,jQuery對(duì)這個(gè)問(wèn)題進(jìn)行了必要的擴(kuò)展和封裝
?$("element").bind("click",function(event){??});???//event為事件對(duì)象event.stopPropagation();???//停止事件冒泡??jquery中可用用preventDefault()的方法來(lái)阻止元素的默認(rèn)行為
$('#submit').bind('click', function(event)?{var?username?=?$('#username').val();if?(username?==?"")?{alert('用戶名不能為空!');event.preventDefault();?//阻止默認(rèn)行為??}})jquery中對(duì)冒泡和默認(rèn)行為的阻止方法可以改寫(xiě),改寫(xiě)后能夠達(dá)到同樣的效果
event.preventDefault(); 改寫(xiě)為: return false; event.stopPropagation(); 改寫(xiě)為: return false;?
轉(zhuǎn)載于:https://my.oschina.net/u/3152390/blog/849505
總結(jié)
以上是生活随笔為你收集整理的JavaScript事件代理和委托的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: docker探索-windows10 d
- 下一篇: 使用Junit对Spring进行单元测试