什么是事件委托?
委托是啥意思?就是本來吧中午啊你要自己去買飯,結(jié)果這個(gè)時(shí)候室友問你要不要帶飯?你說好??!于是帶飯這個(gè)操作就被你委托給室友了。
事件委托 的意思是,本來這個(gè)事件是由節(jié)點(diǎn)本身去執(zhí)行的,現(xiàn)在用其他節(jié)點(diǎn)委托執(zhí)行。
怎么進(jìn)行事件委托?
我們來看一個(gè)再普通不過的例子吧,有以下html結(jié)構(gòu)
<ul id="delegate">
<li>item1</li>
<li>item2</li>
<li>item3</li>
<li>item4</li>
<li>item5</li>
</ul>
假設(shè)這時(shí)候有需求如下,我希望鼠標(biāo)經(jīng)過li節(jié)點(diǎn)的時(shí)候,節(jié)點(diǎn)的背景色變?yōu)榧t色,鼠標(biāo)移出則變回來,我們通常會(huì)這么寫
<script type="text/javascript">
var aUl=document.querySelector('#delegate');
var aLis=div.querySelectorAll('li');
for (var i = 0; i < aLis.length; i++) {
aLis[i].onmouseover=function(){
this.style.backgroundColor='red';
}
aLis[i].onmouseout=function(){
this.style.backgroundColor='';
}
}
</script>
沒毛病哈~那么問題來了,我們?cè)趺窗?code>li的事件委托給其他節(jié)點(diǎn)替他執(zhí)行呢?
首先說下事件委托的原理是利用什么,大家都知道js里面事件有冒泡機(jī)制,當(dāng)我們鼠標(biāo)經(jīng)過li的時(shí)候它的onmouseover事件會(huì)觸發(fā),它的父親元素ul的onmouseover事件也會(huì)被觸發(fā),事件委托就是利用事件冒泡機(jī)制來完成的。不多說上代碼
var aUl=document.querySelector('#delegate');
var aLis=div.querySelectorAll('li');
aUl.onmouseover=function(ev){
var ev=ev||window.event;//事件對(duì)象兼容
var target=ev.target||ev.srcElement;//冒泡時(shí)拿到當(dāng)前的觸發(fā)事件的元素(事件源)
target.style.backgroundColor='red';
}
aUl.onmouseout=function(ev){
var ev=ev||window.event;
var target=ev.target||ev.srcElement;
target.style.backgroundColor='';
}
以上代碼就完成了最簡單的事件委托,是不是很簡單?但是問題來了,這樣寫有沒有問題?
答案是:有?。?!
我們給 ul 添加的onmouseover和onmouseout事件,那么鼠標(biāo)經(jīng)過 ul ,ul的背景也是會(huì)邊紅的?。?!
那么怎么辦?
其實(shí)我們獲取到事件源之后,事件源是一個(gè) DOM 節(jié)點(diǎn),我們是可以拿到節(jié)點(diǎn)的名字 target.nodeName,我們只需要判斷下節(jié)點(diǎn)名字就行啦?。?!來來來!?。?/p>
aUl.onmouseover=function(ev){
var ev=ev||window.event;
var target=ev.target||ev.srcElement;
console.log(target.nodeName);
if(target.nodeName=='LI'){
target.style.backgroundColor='red';
}
}
aUl.onmouseout=function(ev){
var ev=ev||window.event;
var target=ev.target||ev.srcElement;
if(target.nodeName=='LI'){
target.style.backgroundColor='';
}
}
這么寫有什么好處呢?
1、對(duì)比委托前和委托后的代碼就知道,本來每個(gè) li 上都有兩個(gè)事件句柄,委托后我們只給 ul 增加了兩個(gè)事件句柄,可以大量節(jié)省內(nèi)存占用,減少事件注冊(cè)
2、通過js代碼新添加li節(jié)點(diǎn)同樣有事件,不用單獨(dú)注冊(cè)(相似如jquery.delegate())
注:事件委托雖然好,但是還是有需要注意的地方的,最明顯的就是我的例子中判斷是不是 li 節(jié)點(diǎn)這個(gè)處理,當(dāng)前節(jié)點(diǎn)結(jié)構(gòu)簡單,如果被委托元素內(nèi)節(jié)點(diǎn)類型眾多,判斷條件就會(huì)很復(fù)雜。