一步一步來說說事件委托(或者有的資料叫事件代理)
- js中事件冒泡我們知道杨何,子元素身上的事件會冒泡到父元素身上唧躲。
- 事件代理就是政模,本來加在子元素身上的事件,加在了其父級身上热某。
- 那就產(chǎn)生了問題:父級那么多子元素,怎么區(qū)分事件本應該是哪個子元素的胳螟?
- 答案是:event對象里記錄的有“事件源”昔馋,它就是發(fā)生事件的子元素。
- “事件源”它存在兼容性問題糖耸,在老的IE下秘遏,事件源是 window.event.srcElement,其他瀏覽器是 event.target
用事件委托有什么好處呢嘉竟? - 第一個好處是效率高邦危,比如,不用for循環(huán)為子元素添加事件了
- 第二個好處是舍扰,js新生成的子元素也不用新為其添加事件了倦蚪,程序邏輯上比較方便
還是用一個例子來說明吧
例子1. 頁面有個ul包含著4個li,鼠標移動到li上边苹,li背景變成紅色陵且,移出,背景恢復原色个束。
如果按照以前的寫法慕购,代碼如下:
<ul id="ul1">
<li>111</li>
<li>222</li>
<li>333</li>
<li>444</li>
</ul>
<script type="text/javascript">
window.onload = function(){
var oUl = document.getElementById('ul1');
var aLi = oUl.children;
console.log(aLi);
//傳統(tǒng)方法,li身上添加事件茬底,需要用for循環(huán)脓钾,找到每個li
for (var i=0;i<aLi.length;i++) {
aLi[i].onmouseover = function() {
this.style.background = 'red';
}
aLi[i].onmouseout = function(){
this.style.background = '';
}
}//for結束
}
</script>
現(xiàn)在用事件委托的方式,onmouseover桩警、onmouseout方法要加在ul身上了可训,再通過找事件源的方式昌妹,改變li背景,代碼如下:
上面ul的html代碼不變握截,js部分變?yōu)?/p>
<script type="text/javascript">
window.onload = function(){
var oUl = document.getElementById('ul1');
oUl.onmouseover = function(ev){
var ev = ev || window.event;
var oLi = ev.srcElement || ev.target;
oLi.style.background = 'red';
}
oUl.onmouseout = function(ev){
var ev = ev || window.event;
var oLi = ev.srcElement || ev.target;
oLi.style.background = '';
}
}
</script>
效果如下:
但是會發(fā)現(xiàn)飞崖,鼠標移到了ul身上而不是某個li身上時,獲取的事件源是ul谨胞,那么整個ul背景將變紅固歪,這不是想要的結果,怎么辦胯努?
答曰:加個判斷牢裳。通過事件源的nodeName判斷是不是li,是才做出反應叶沛,不是不理它蒲讯。為了防止nodeName在不同瀏覽器獲取的字母大小寫不同,加個toLowerCase()
所以灰署,上面的js代碼更改如下:
<script type="text/javascript">
window.onload = function(){
var oUl = document.getElementById('ul1');
oUl.onmouseover = function(ev){
var ev = ev || window.event;
var oLi = ev.srcElement || ev.target;
if(oLi.nodeName.toLowerCase() == 'li'){
oLi.style.background = 'red';
}
}
oUl.onmouseout = function(ev){
var ev = ev || window.event;
var oLi = ev.srcElement || ev.target;
if(oLi.nodeName.toLowerCase() == 'li'){
oLi.style.background = '';
}
}
}
</script>
這就不用for循環(huán)寫一堆了判帮,下面再來說說第二個好處:js新生成的子元素也不用新為其添加事件了,程序邏輯上比較方便
上面的文件溉箕,假如我再新添加個按鈕晦墙,點擊按鈕,ul里就新增加個li肴茄,如果用傳統(tǒng)的方法晌畅,for循環(huán)為li添加事件,問題就出現(xiàn)了寡痰,最開始有的4個li是有onmouseover和onmouseout事件的踩麦,但是后來動態(tài)生成的li里沒有這兩個事件處理函數(shù),因為for循環(huán)的時候它還沒生成氓癌。怎么辦呢谓谦?只能在按鈕點擊后,生成li贪婉,然后再為生成的li再綁定事件反粥,真是麻煩的很。而事件委托的方式就沒事疲迂,當后來動態(tài)生成的li出現(xiàn)的時候才顿,不用做改變,移到它身上尤蒿,還是變色的郑气,因為事件是綁定在ul身上的。
新浪微博里腰池,當你發(fā)一條新微博出去尾组,發(fā)出去的信息在頁面上顯示忙芒,鼠標移動到新發(fā)的信息的人頭像上時,依然會有很多事件讳侨,如果用原來的方式呵萨,就要做很多處理,事件委托的話跨跨,就很方便了潮峦!