標籤:事件處理 順序 listen false 程式員 document 方式 分時 js代碼
一、什麼是JavaScript事件?
事件(Event)是JavaScript應用跳動的心臟,也是把所有東西粘在一起的膠水,當我們與瀏覽器中Web頁面進行某些類型的互動時,事件就發生了。
事件可能是使用者在某些內容上的點擊、滑鼠經過某個特定元素或按下鍵盤上的某些按鍵,事件還可能是Web瀏覽器中發生的事情,比如說某個Web頁面載入完成,或者是使用者滾動視窗或改變視窗大小。
說白了,事件是文檔或瀏覽器中發生的特定互動瞬間!
通過使用JavaScript,你可以監聽特定事件的發生,並規定讓某些事件發生以對這些事件做出響應(具體代碼大家可以通過馬海祥部落格《JS基礎知識:Javascript事件觸發列表》的表格來查詢)。
二、事件流
事件流就是描述了頁面中接受事件的順序,在瀏覽器發展的初期,兩大瀏覽器廠商IE和Netscape互掐,出現了一個坑爹的情況,那就是他們對事件流的解釋出現了兩中截然相反的定義。也就是我們所熟悉的:IE的事件冒泡,Netscape的事件捕獲。先來一張圖,簡要的看下結構:
1、事件冒泡
事件冒泡即事件最開始由最具體的元素(文檔中嵌套層次最深的那個節點)接收,然後逐級向上傳播至最不具體的節點(文檔)。拿上面的圖來說明,就是當點擊text部分時,先由text處的元素接收,然後逐級傳播至window,即執行6-7-8-9-10的過程。
2、事件捕獲
事件捕獲即事件最早由不太具體的節點接收,而最具體的節點最後接收到事件。同理,在上面的模型中,就是點擊text部分時,先由window接收,然後逐級傳播至text元素,即執行1-2-3-4-5的過程。
具體在代碼中怎樣表現呢?後面馬海祥會給出代碼的介紹,大家莫急!
三、Javascript事件處理常式的3種方式
產生了事件,我們就要去處理他,據馬海祥瞭解Javascript事件處理常式主要有3種方式:
1、HTML事件處理常式
即我們直接在HTML代碼中添加事件處理常式,如下面這段代碼:
<input id="btn1" value="按鈕" type="button" onclick="showmsg();">
<script>
function showmsg(){
alert("HTML添加事件處理");
}
</script>
從上面的代碼中我們可以看出,事件處理是直接嵌套在元素裡頭的,這樣有一個毛病:就是html代碼和js的耦合性太強,如果哪一天我想要改變js中showmsg,那麼我不但要再js中修改,我還需要到html中修改,一兩處的修改我們能接受,但是當你的代碼達到萬行層級的時候,修改起來就需要勞民傷財了,所以,這個方式我們並不推薦使用。
2、DOM0級事件處理常式
即為指定對象添加事件處理,看下面的一段代碼
<input id="btn2" value="按鈕" type="button">
<script>
var btn2= document.getElementById("btn2");
btn2.onclick=function(){
alert("DOM0級添加事件處理");
}
btn.onclick=null;//如果想要刪除btn2的點擊事件,將其置為null即可
</script>
從上面的代碼中,我們能看出,相對於HTML事件處理常式,DOM0級事件,html代碼和js代碼的耦合性已經大大降低。但是,聰明的程式員還是不太滿足,期望尋找更簡便的處理方式,下面馬海祥就來說說第三種處理方法。
3、DOM2級事件處理常式
DOM2也是對特定的對象添加事件處理常式(具體可查看馬海祥部落格的《JavaScript對象屬性的基礎教程指南》相關介紹),但是主要涉及到兩個方法,用於處理指定和刪除事件處理常式的操作:addEventListener()和 removeEventListener()。
它們都接收三個參數:要處理的事件名、作為事件處理常式的函數和一個布爾值(是否在捕獲階段處理事件),看下面的一段代碼:
<input id="btn3" value="按鈕" type="button">
<script>
var btn3=document.getElementById("btn3");
btn3.addEventListener("click",showmsg,false);//這裡我們把最後一個值置為false,即不在捕獲階段處理,一般來說冒泡處理在各瀏覽器中相容性較好
function showmsg(){
alert("DOM2級添加事件處理常式");
}
btn3.removeEventListener("click",showmsg,false);//如果想要把這個事件刪除,只需要傳入同樣的參數即可
</script>
這裡我們可以看到,在添加刪除事件處理的時候,最後一種方法更直接,也最簡便。但是馬海祥提醒大家需要注意的是,在刪除事件處理的時候,傳入的參數一定要跟之前的參數一致,否則刪除會失效!
四、事件冒泡和事件捕獲的流程與區別
說到這裡,馬海祥再給大家來一點代碼來說明下事件冒泡和事件捕獲的流程,同時也讓大家能看出二者的區別:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
#p{width:400px;height:200px;border:1px solid black;}
#c{width:200px;height:100px;border:1px solid red;}
</style>
</head>
<body>
<div id="p">
i am www.mahaixiang.cn
<div id="c">i like www.mahaixiang.cn</div>
</div>
<script>
var p = document.getElementById(‘p‘);
var c = document.getElementById(‘c‘);
c.addEventListener(‘click‘, function () {
alert(‘子節點捕獲‘)
}, true);
c.addEventListener(‘click‘, function () {
alert(‘子節點冒泡‘)
}, false);
p.addEventListener(‘click‘, function () {
alert(‘父節點捕獲‘)
}, true);
p.addEventListener(‘click‘, function () {
alert(‘父節點冒泡‘)
}, false);
</script>
</body>
</html>
運行上面的代碼,點擊子項目的時候,我們會發現,執行的先後順序是:父節點捕獲--子節點捕獲--子節點冒泡--父節點冒泡。從這個例子中,大家也就明白了,另外,DOM2級事件規定事件包括三個階段:
1、事件捕獲階段;
2、處於目標階段;
3、事件冒泡階段。
首先是捕獲,然後處於目標階段(即來到事件的發出位置),最後才是冒泡,
不科學的是,居然木有DOM1級事件處理常式,大家注意下,別鬧出笑話了!
馬海祥部落格補充:IE事件處理常式也對應有兩個方法:attachEvent()添加事件,detachEvent()刪除事件,這兩個方法接收相同的兩個參數:事件處理常式名稱與事件處理函數。
這裡為什麼沒有布爾值呢?因為ie8以及更早的版本只支援事件冒泡,所以最後一個參數預設的相當於false來處理!(支援IE事件處理常式的瀏覽器有IE,opera)
五、事件處理常式的瀏覽器安全色性
既然不同的瀏覽器對事件處理常式有這自己不同的支援,那麼,我們在開發中,豈不是每次使用事件處理常式時都要對不同的瀏覽器做一次相容?這裡馬海祥封裝一個相容方法,以後在事件處理的時候,直接調用即可,看下面一段代碼:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<input id="btn" type="button" value="按鈕">
<script>
var eventHandler={
addHandler:function(element,type,func){
if(element.addEventListener){
element.addEventListener(type,func,false);
}else if(element.detachEvent){
element.attachEvent(‘on‘+type,func);
}else{
element[‘on‘+type]=func;
}
},
removerHandler:function(element,type,func){
if(element.removeEventListener){
element.removeEventListener(type,func,false);
}else if(element.detachEvent){
element.detachEvent(‘on‘+type,func);
}else{
element[‘on‘+type]=null;
}
}
}
function showmsg(){
alert("hello");
}
var btn=document.getElementById("btn");
eventHandler.addHandler(btn,"click",showmsg);
//eventHandler.removerHandler(btn,"click",showmsg);//去掉事件處理
</script>
</body>
</html>
上面的代碼在ie和其他瀏覽器中都能正常處理事件,以後如果需要使用相容性的操作,都可以直接調用這段代碼。
馬海祥部落格點評:
事件對象是用來記錄一些事件發生時的相關資訊的對象,但事件對象只有事件發生時才會產生,並且只能是事件處理函數內部訪問,在所有事件處理函數運行結束後,事件對象就被銷毀!
本文為馬海祥部落格原創文章,如想轉載,請註明原文網址摘自於http://www.mahaixiang.cn/js/694.html,註明出處;否則,禁止轉載;謝謝配合!
JavaScript事件處理常式的3種方式