了解javascript中的事件(一)


本人目錄如下:

零、寒暄

  由於剛入職,近期事情繁多,今天好不容易中期答辯完事,晚上有一些時間,來給大家分享一篇博文。

  這段時間每天寫js接觸事件比較多,自己會使用,但是用的時候比較混亂,現在系統的整理下,好了,閑話不多說,談正事!

一、事件概念

  什么是事件?說白了,事件是文檔或瀏覽器中發生的特定交互瞬間!比如鼠標點擊,滑過等等。

二、事件流

  事件流就是描述了頁面中接受事件的順序。在瀏覽器發展的初期,兩大瀏覽器廠商IE和Netscape互掐,出現了一個坑爹的情況,那就是他們對事件流的解釋出現了兩中截然相反的定義。也就是我們所熟悉的:IE的事件冒泡,Netscape的事件捕獲。先來一張圖,簡要的看下結構(以前網上看到的,也不知道出處了,盜用一下,感謝原作者辛勤的visio畫圖,哈哈)

2.1事件冒泡

  概念:事件冒泡即事件最開始由最具體的元素(文檔中嵌套層次最深的那個節點)接收,然后逐級向上傳播至最不具體的節點(文檔)。拿上面的圖來說明,就是當點擊text部分時,先由text處的元素接收,然后逐級傳播至window,即執行6-7-8-9-10的過程。

2.2事件捕獲

  概念:事件捕獲即事件最早由不太具體的節點接收,而最具體的節點最后接收到事件。同理,在上面的模型中,就是點擊text部分時,先由window接收,然后逐級傳播至text元素,即執行1-2-3-4-5的過程。

  具體在代碼中怎樣表現呢,后面會給出代碼的介紹,客官莫急。

三、事件處理程序

  產生了事件,我們就要去處理他。事件處理程序主要有三種方式:
  3.1 HTML事件處理程序

  即我們直接在HTML代碼中添加事件處理程序。來一段代碼吧,寫了這么久沒有代碼實在是憋得慌,哎,程序員的毛病!

1 <input id="btn1" value="按鈕" type="button" onclick="showmsg();">
2 <script>
3     function showmsg(){
4         alert("HTML添加事件處理");
5     }
6 </script>

  從上面的代碼中我們可以看出,事件處理是直接嵌套在元素里頭的,這樣有一個毛病:就是html代碼和js的耦合性太強,如果哪一天我想要改變js中showmsg,那么我不但要再js中修改,我還需要到html中修改,一兩處的修改我們能接受,但是當你的代碼達到萬行級別的時候,修改起來就需要勞民傷財了,所以這個方式我們並不推薦使用。

  3.2 DOM0級事件處理程序

  即為指定對象添加事件處理。慣例,看下面的一段代碼

1 <input id="btn2" value="按鈕" type="button">
2 <script>
3   var btn2= document.getElementById("btn2");
4     btn2.onclick=function(){
5     alert("DOM0級添加事件處理");
6   }  
7   btn.onclick=null;//如果想要刪除btn2的點擊事件,將其置為null即可 
8 </script>  

  從上面的代碼中,我們能看出,相對於HTML事件處理程序,DOM0級事件,html代碼和js代碼的耦合性已經大大降低。但是,聰明的程序員還是不太滿足,期望尋找更簡便的處理方式,下面我們來說第三種處理方法。

 3.3 DOM2級事件處理程序

  DOM2也是對特定的對象添加事件處理程序,但是主要涉及到兩個方法,用於處理指定和刪除事件處理程序的操作:addEventListener()和 removeEventListener()。

  它們都接收三個參數:要處理的事件名、作為事件處理程序的函數和一個布爾值(是否在捕獲階段處理事件)。看下面的一段代碼:

1 <input id="btn3" value="按鈕" type="button">
2 <script>
3     var btn3=document.getElementById("btn3");
4     btn3.addEventListener("click",showmsg,false);//這里我們把最后一個值置為false,即不在捕獲階段處理,一般來說冒泡處理在各瀏覽器中兼容性較好
5     function showmsg(){
6         alert("DOM2級添加事件處理程序");
7     }
8     btn3.removeEventListener("click",showmsg,false);//如果想要把這個事件刪除,只需要傳入同樣的參數即可
9 </script>

  這里我們可以看到,在添加刪除事件處理的時候,最后一種方法更直接,也最簡便。但是需要注意的是,在刪除事件處理的時候,傳入的參數一定要跟之前的參數一致,否則刪除會失效!

  說到這里,我們來一點代碼來說明下事件冒泡和事件捕獲的流程,同時也讓大家能看出二者的區別 

 1 <!doctype html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>Document</title>
 6     <style>
 7         #p{width:400px;height:200px;border:1px solid black;}
 8         #c{width:200px;height:100px;border:1px solid red;}
 9     </style>
10 
11 </head>
12 <body>
13     <div id="p">
14         i am parent
15         <div id="c">i am children</div>
16     </div>
17     <script>
18      var p = document.getElementById('p');
19        var c = document.getElementById('c');
20        c.addEventListener('click', function () {
21             alert('子節點捕獲')
22         }, true);
23 
24        c.addEventListener('click', function () {
25             alert('子節點冒泡')
26        }, false);
27 
28        p.addEventListener('click', function () {
29              alert('父節點捕獲')
30          }, true);
31  
32        p.addEventListener('click', function () {
33            alert('父節點冒泡')
34         }, false);
35     </script>
36 </body>
37 </html>

運行上面的代碼,點擊子元素的時候,我們會發現,執行的先后順序是:父節點捕獲--子節點捕獲--子節點冒泡--父節點冒泡。從這個例子中,大家也能明白,為什么說

  DOM2級事件規定事件包括三個階段:

    1)事件捕獲階段;2)處於目標階段;3)事件冒泡階段

  首先是捕獲,然后處於目標階段(即來到事件的發出位置),最后才是冒泡,

  嚴重PS:不科學的是,居然木有DOM1級事件處理程序,大家注意下,別鬧出笑話了!

  【補充】IE事件處理程序也對應有兩個方法:attachEvent()添加事件,detachEvent()刪除事件,這兩個方法接收相同的兩個參數:事件處理程序名稱與事件處理函數。這里為什么沒有布爾值呢?因為ie8以及更早的版本只支持事件冒泡,所以最后一個參數默認的相當於false來處理!(支持IE事件處理程序的瀏覽器有IE,opera)

3.4 事件處理程序的瀏覽器兼容性

  既然不同的瀏覽器對事件處理程序有這自己不同的支持,那么,我們在開發中,豈不是每次使用事件處理程序時都要對不同的瀏覽器做一次兼容?這里我們封裝一個兼容方法,以后在事件處理的時候,直接調用即可,看下面一段代碼:

 1 <!doctype html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>Document</title>
 6 </head>
 7 <body>
 8 <input id="btn" type="button" value="按鈕">
 9     <script>
10     var eventHandler={
11         addHandler:function(element,type,func){
12             if(element.addEventListener){
13                 element.addEventListener(type,func,false);
14             }else if(element.attachEvent){
15                 element.attachEvent('on'+type,func);
16             }else{
17                 element['on'+type]=func;
18             }
19         },
20         removerHandler:function(element,type,func){
21             if(element.removeEventListener){
22                 element.removeEventListener(type,func,false);
23             }else if(element.detachEvent){
24                 element.detachEvent('on'+type,func);
25             }else{
26                 element['on'+type]=null;
27             }
28         }
29     }
30     function showmsg(){
31         alert("hello");
32     }
33     var btn=document.getElementById("btn");
34     eventHandler.addHandler(btn,"click",showmsg);
35     //eventHandler.removerHandler(btn,"click",showmsg);//去掉事件處理
36     </script>
37 </body>
38 </html>

  上面的代碼在ie和其他瀏覽器中都能正常處理事件,以后如果需要使用兼容性的操作,都可以直接調用這段代碼。

四、總結

  js中事件是一塊很大的部分,今天主要說了一些概念,和常用函數的使用,下次我將跟大家分享下事件的分類、事件代理,以及事件代理思想的用處。總之,精彩紛呈。歡迎圍觀。PS:JS中的事件(二)已經完成,歡迎大家猛擊這里

  好了,寫了這么多,不知不覺已經很晚了,明天還要上班,今天先到此為止。

  本文中肯定有很多紕漏和理解不對的地方,如果大家發現有問題的,可以跟我留言討論(接受批評!),各位,晚安!

此文章發布在本人博客園rookiebob,如需轉載本文,請務必注明來源: http://www.cnblogs.com/rookiebob/,有些勘誤我會及時更正,為了避免對您的誤解,請訪問原文!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM