淺談事件監聽
自從學了事件監聽之後,覺得他真是個好東西~~,為什麽呢?
首先說下他的好處:第一點:他可以實現對未來元素事件的綁定【?未來元素:就是在綁定事件時,頁面上還不存在的元素】;第二點:減少事件綁定,提高性能【我們知道前端主要是解決性能優化和兼容問題的,所有這個就挺重要了】
下面來捋一捋事件監聽一個比較全面的見解?
1、關於事件
事件分為DOM 0級事件和Dom 2級事件,DOM2級事件也叫做事件監聽。DOM 0級事件的缺點是如果事件相同 後者的事件會覆蓋前者的事件,DOM2級事件可以解決這個問題
document.onclick = function(){ alert(1); } document.onclick= function(){ alert(2); } //只會執行第二個函數 彈出2
2、DOM2級事件的方法
主流瀏覽器: addEventListener() 【有三個參數】
參數1:事件類型 不需要加on
參數2:回調函數名稱 (函數需要單獨寫在外面)
參數3:布爾值 true代表捕獲 false代表冒泡
解綁事件方法:removeEventListener()
首先寫兩個方法:
function a(){ alert(1) } function b(){ alert(2) } document.addEventListener("click",a); document.addEventListener("click",b); //點擊後先執行第一個函數,再執行第二個函數 document.removeEventListener("click",a) //不在執行a()這個函數
IE瀏覽器下用:attachEvent() 【有兩個參數】
參數1:事件類型 需要加on
參數2:回調函數名稱(函數需要單獨寫在外面)
解綁事件方法:detachEvent()
function a(){ alert(1) } function b(){ alert(2) } document.attachEvent("onclick",a); document.attachEvent("onclick",b);//點擊後先執行第二個函數,再執行第一個函數 document.detachEvent("onclick",a)//不在執行a()這個函數
3、事件流、事件冒泡、事件捕獲
當一個HTML元素產生一個事件時,該事件會在元素節點與根節點之間的路徑傳播,路徑所經過的節點都會收到該事件,這個傳播的過程叫做DOM事件流
元素觸發事件時,事件的傳播過程稱為事件流,過程分為捕獲和冒泡兩種
冒泡事件:微軟提出的 事件由子元素傳遞到父元素的過程,叫做冒泡
舉個栗子:
HTML布局如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style type="text/css"> #box{width:200px;height:200px;background:#ff3;} #innerBox{width:100px;height:100px;background:blue;} </style> </head> <body> <div id="box"> <div id="innerBox"></div> </div> </body> </html>
Js代碼如下:
var box=document.getElementById("box");
var innerBox=document.getElementById("innerBox");
document.addEventListener("click",function(){
alert("document-------冒泡");
},false);
document.body.addEventListener("click",function(){
alert("body-------冒泡");
},false);
box.addEventListener("click",function(){
alert("box-------冒泡");
},false);
innerBox.addEventListener("click",function(){
alert("innerBox-------冒泡");
},false);
點擊innerBox後:
執行的順序是innerBox==》box==》body===》document
代碼輸出順序是:innerBox-------冒泡=====》box-------冒泡====》body-------冒泡====》document-------冒泡
如果點擊box的話
執行的順序是box==》body===》document
代碼輸出順序是:box-------冒泡====》body-------冒泡====》document-------冒泡
捕獲事件:網景提出的 事件由父元素到子元素傳遞的過程,叫做事件捕獲
Js代碼如下:
var box=document.getElementById("box");
var innerBox=document.getElementById("innerBox");
document.addEventListener("click",function(){
alert("document-------捕獲");
},true);
document.body.addEventListener("click",function(){
alert("body-------捕獲");
},true);
box.addEventListener("click",function(){
alert("box-------捕獲");
},true);
innerBox.addEventListener("click",function(){
alert("innerBox-------捕獲");
},true);
點擊innerBox後
執行的順序是document==》body==》box===》innerBox
代碼輸出順序是:document-------捕獲=====》body-------捕獲====》box-------捕獲====》innerBox-------捕獲
如果點擊box的話
執行的順序是:document==》body==》box
代碼輸出順序是:document-------捕獲=====》body-------捕獲====》box-------捕獲
以下兩個情況值得註意一下:
1、當事件冒泡和捕獲同時執行的時候,是什麽順序?
Js代碼如下:
document.addEventListener("click",function(){ alert("document-------捕獲"); },true); document.body.addEventListener("click",function(){ alert("body-------捕獲"); },true); box.addEventListener("click",function(){ alert("box-------捕獲"); },true); innerBox.addEventListener("click",function(){ alert("innerBox-------捕獲"); },true); document.addEventListener("click",function(){ alert("document-------冒泡"); },false); document.body.addEventListener("click",function(){ alert("body-------冒泡"); },false); box.addEventListener("click",function(){ alert("box-------冒泡"); },false); innerBox.addEventListener("click",function(){ alert("innerBox-------冒泡"); },false);
如果點擊innerBox的話:
代碼輸出順序是:document-------捕獲=====》body-------捕獲====》box-------捕獲====》innerBox-------捕獲innerBox-------冒泡=====》box-------冒泡====》body-------冒泡====》document-------冒泡
也就是說當事件冒泡和捕獲同時執行的時候執行順序是:先執行捕獲後執行冒泡
2、當事件冒泡和捕獲同時執行的時候 冒泡事件和捕獲事件到最底層的時候順序發生改變的話:
Js代碼如下:
document.addEventListener("click",function(){ alert("document-------捕獲"); },true); document.body.addEventListener("click",function(){ alert("body-------捕獲"); },true); box.addEventListener("click",function(){ alert("box-------捕獲"); },true); innerBox.addEventListener("click",function(){ alert("innerBox-------冒泡"); },false); innerBox.addEventListener("click",function(){ alert("innerBox-------捕獲"); },true); document.addEventListener("click",function(){ alert("document-------冒泡"); },false); document.body.addEventListener("click",function(){ alert("body-------冒泡"); },false); box.addEventListener("click",function(){ alert("box-------冒泡"); },false);
點擊innerBox後
代碼輸出順序是:document-------捕獲=====》body-------捕獲====》box-------捕獲====》innerBox-------冒泡innerBox-------捕獲=====》box-------冒泡====》body-------冒泡====》document-------冒泡
也就是說冒泡事件和捕獲事件到最底層的時候如果順序發生改變的話:到最底層的時候是順序執行
4、IE與火狐的事件機制區別?
事件處理機制:IE是事件冒泡、火狐是 事件捕獲;
5、事件代理/事件委托
利用冒泡機制,將子元素的事件委托給父元素去監聽(給父元素添加事件),當子元素觸發事件時,事件冒泡到父級如果希望指定的子元素才能觸發事件,可以通過事件對象(event)獲得事件源(target),然後通過條件判斷是不是期望的子元素,如果是的話,執行事件,否則不執行。
下面舉個小栗子簡單介紹一下:
HTML結構:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style type="text/css"> a{text-decoration: none;padding:0 5px;} table td{height:24px;line-height:24px;} </style> </head> <body> <button id="btn">添加</button> <table border="1" id="tab"> <tr> <td>333</td> <td><a href="##">查看</a><a href="##" class="delbtn">刪除</a></td> </tr> </table> </body> </html>
JS代碼: <script> var btn=document.getElementById("btn"); var tab=document.getElementById("tab"); var str=""; //現在想要做的效果是 每次點擊添加按鈕都會在table裏面添加一行 //如果點擊刪除 則會刪除table裏的一整行 btn.onclick=function(){ //給添加按鈕 添加點擊事件 str=‘<tr><td>333</td><td><a href="##">查看</a><a href="##" class="delbtn">刪除</a></td></tr>‘; tab.innerHTML+=str; //將內容添加到table裏面 } tab.onclick=function(e){ //給父級添加事件 var e=e||event; //事件對象兼容性問題 var target=e.target||e.srcElement; //事件源target 兼容性問題 if(target.tagName=="A" && target.className=="delbtn"){ //條件判斷找到子元素【刪除按鈕】 target.parentNode.parentNode.remove(); } } </script>
效果圖如下:
6、如何找到事件源
var target = e.target || e.srcElement
其中: tagName能找到事件源的元素名 className 能找到事件源的類名
淺談事件監聽