深入分析Javascript事件代理
很久很久以來(lái),總感覺(jué)事件發(fā)生與事件代理到之間沒(méi)什么鳥區(qū)別。
最近,又看了一下,感覺(jué)區(qū)別其實(shí)真不大!看怎么理解吧。
要搞清楚什么是事件代理,就需要先搞清楚什么是代理。
從商業(yè)角度來(lái)講,代理就是:我有貨,你沒(méi)貨,但丫我沒(méi)時(shí)間、沒(méi)精力全部賣掉,而你一天閑的蛋疼,只剩下時(shí)間了。于是,我委托你幫我買,然后哥給你提成。這個(gè)過(guò)程中,你實(shí)際上相當(dāng)于也有了貨。
OK,怎么從字面來(lái)理解事件代理一詞的含義?后文有講。
一 先看一個(gè)真實(shí)的,新手綁定onclik事件的例子
如果按照之前的我,我會(huì)怎么給每一個(gè)li標(biāo)簽,添加onlick呢?廢話,要是我,肯定簡(jiǎn)單粗暴。
循環(huán)每一個(gè)li,然后全部綁定onlick。
于是我的代碼應(yīng)該是這樣子:
<ul id="thl"> <li>001</li> <li>002</li> <li>003</li> </ul> <script> var thl= document.getElementById('thl'); var aLi = thl.getElementsByTagName('li'); for (var i = 0; i < aLi.length; i++) { aLi[i].onclick = fn; } function fn (){ console.log("maomaoliang"); } </script>
好像看起來(lái)沒(méi)問(wèn)題了。雖然,有些文章說(shuō)這樣很消耗性能,但是,我丫電腦好,老子管你性能,不能太認(rèn)真。
二 突然有一天,我發(fā)現(xiàn)通過(guò)js添加進(jìn)來(lái)的新的li,沒(méi)有綁定onlcik
var node=document.createElement("li"); var textnode=document.createTextNode("maomaoliang"); node.appendChild(textnode); document.getElementById("ul1").appendChild(node);
然后,點(diǎn)擊maomaoliang,它并沒(méi)有綁定我的onlick,這是為什么?
哦,原來(lái),我原有的li跟我后面生成的li根本不是同時(shí)發(fā)生的,在創(chuàng)建新的li元素之前,已經(jīng)給存在的li加事件了。好吧,好煩啊。
三 那怎么破?
然后,又好(無(wú))奇(奈)的看了一些文章,原來(lái)有個(gè)叫事件代理的東西可以用。我就試試看吧!于是改寫了部分代碼,像這樣:
var thl= document.getElementById('thl'); thl.onclick = function(ev) { ev = ev || event; //兼容處理 var target = ev.target || ev.srcElement; //找到li元素 if (target.nodeName.toLowerCase() == 'li') { fn(); } }; function fn (){ console.log("maomaoliang"); }
結(jié)果,點(diǎn)擊新的li,居然也觸發(fā)了fn函數(shù)。好吧,身為一個(gè)好奇心驅(qū)動(dòng)的肉身,我怎么能不求甚解呢?還是要踏實(shí)點(diǎn),搞清楚這其中的奧秘才行。
于是,看了事件代理的資料。
首先,要知道什么是事件冒泡:當(dāng)一個(gè)元素上的事件被觸發(fā)的時(shí)候,比如說(shuō)鼠標(biāo)點(diǎn)擊了一個(gè)按鈕,同樣的事件將會(huì)在那個(gè)元素的所有祖先元素中被觸發(fā)。這一過(guò)程被稱為事件冒泡。
然后,再回到之前的問(wèn)題“怎么從字面來(lái)理解事件代理一詞的含義”,誰(shuí)代理了事件?或者事件代理了誰(shuí)?
以本文的例子來(lái)講,看看改動(dòng)后的代碼,我把onlick事件綁定到了ul標(biāo)簽上面,而不是li標(biāo)簽。于是,當(dāng)我點(diǎn)擊任何一個(gè)li標(biāo)簽(不管是動(dòng)態(tài)生成的還是之前就有的)是,這個(gè)事件就像泡泡一樣,冒啊冒。正常的情況下,ul也會(huì)綁定onclick,body也會(huì)綁定到onclick,也就說(shuō)它會(huì)冒泡到最根層的元素。但我這里給ul綁定了onlick,那么這時(shí),ul會(huì)把泡泡截住,事件也就停止上升,無(wú)法抵達(dá)body標(biāo)簽。
接著, var target = ev.target || ev.srcElement;這一句話,相當(dāng)于告訴了我,我究竟點(diǎn)的是誰(shuí),誰(shuí)才是target。如果,這個(gè)target剛剛好就是li標(biāo)簽if (target.nodeName.toLowerCase() == 'li'),那么執(zhí)行fn函數(shù)。
最后,我驕傲的回答了那個(gè)問(wèn)題:table代理了onlick事件!
四 回憶一下事件代理的步驟
父元素綁定事件
父元素知道事件的實(shí)際發(fā)生目標(biāo)是誰(shuí)
我們要對(duì)目標(biāo)進(jìn)行判斷,如果是我們需要的元素,則發(fā)生回調(diào)函數(shù)(所以要學(xué)好選擇器的使用)
五 最后總結(jié),事件代理兩大好處
性能不小心得到了優(yōu)化
動(dòng)態(tài)添加的元素也能綁定事件了
六 需要注意的一點(diǎn)是
上述針對(duì)的是原生js事件綁定來(lái)講的,如果你用到了jquery。并把代碼改成了如下的樣子:
/*var thl= document.getElementById('ul1'); thl.onclick = function(ev) { ev = ev || event; //兼容處理 var target = ev.target || ev.srcElement; //找到li元素 if (target.nodeName.toLowerCase() == 'li') { //li添加的事件 fn(); } };*/ var node=document.createElement("li"); var textnode=document.createTextNode("maomaoliang"); node.appendChild(textnode); document.getElementById("ul1").appendChild(node); function fn (){ console.log("maomaoliang"); } $("#ul1").click(function(){ fn(); });
這樣一來(lái),新添加的li標(biāo)簽,也能綁click,是不是很方便、很簡(jiǎn)單,是不是感覺(jué)學(xué)js沒(méi)什么卵用。
哈哈,這樣想很正常,我以前也這么想,但是,做了一些東西之后,發(fā)現(xiàn)jquery還真的不夠用了!但是基本夠用!
雖然,大神們都說(shuō)要學(xué)js,但我還是覺(jué)得可以先學(xué)jquery,之后再學(xué)js,效果也可以的。
相關(guān)文章
Javascript 普通函數(shù)和構(gòu)造函數(shù)的區(qū)別
這篇文章主要介紹了Javascript 普通函數(shù)和構(gòu)造函數(shù)的區(qū)別的相關(guān)資料,需要的朋友可以參考下2016-11-11淺談JavaScript_DOM學(xué)習(xí)篇_圖片切換小案例
這篇文章主要介紹了JavaScriptDOM圖片切換小案例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-03-03javascript事件綁定學(xué)習(xí)要點(diǎn)
這篇文章主要介紹了javascript事件綁定學(xué)習(xí)要點(diǎn),主要包含下面四個(gè)方面1.傳統(tǒng)事件綁定的問(wèn)題,2.W3C事件處理函數(shù),3.IE事件處理函數(shù),4.事件對(duì)象的其他補(bǔ)充,有需要的小伙伴可以參考下2016-03-03用meta實(shí)現(xiàn)的頁(yè)面跳轉(zhuǎn)代碼
用meta實(shí)現(xiàn)的頁(yè)面跳轉(zhuǎn)代碼,建議與js一起使用,防止頁(yè)面假死或不支持js的情況,都可以實(shí)現(xiàn)效果。2007-09-09JavaScript中的分號(hào)插入機(jī)制詳細(xì)介紹
這篇文章主要介紹了JavaScript中的分號(hào)插入機(jī)制詳細(xì)介紹,本文講解JavaScript中各種情況下的分號(hào)插入機(jī)制,需要的朋友可以參考下2015-02-02