閱讀522 返回首頁    go 阿裏雲 go 技術社區[雲棲]


JavaScript 事件

什麼是JavaScript事件

事件(Event)是JavaScript應用跳動的心髒,也是把所有東西粘在一起的膠水,當我們與瀏覽器中Web頁麵進行某些類型的交互時,事件就發生了;通過使用JavaScript,你可以監聽特定事件的發生,並規定讓某些事件發生以對這些事件做出響應

事件對象是用來記錄一些事件發生時的相關信息的對象,但事件對象隻有事件發生時才會產生,並且隻能是事件處理函數內部訪問,在所有事件處理函數運行結束後,事件對象就被銷毀

事件流

事件流就是描述了頁麵中接受事件的順序,在瀏覽器發展的初期,兩大瀏覽器廠商IE和Netscape互掐,出現了一個坑爹的情況,那就是他們對事件流的解釋出現了兩中截然相反的定義。也就是我們所熟悉的:IE的事件冒泡,Netscape的事件捕獲

事件冒泡

事件冒泡即事件最開始由最具體的元素(文檔中嵌套層次最深的那個節點)接收,然後逐級向上傳播至最不具體的節點(文檔)

事件捕獲

事件捕獲即事件最早由不太具體的節點接收,而最具體的節點最後接收到事件

Javascript事件處理程序的3種方式

內聯形式

耦合度高,不利於維護

<button >點擊這個按鈕</button>

HTML事件處理程序

即我們直接在HTML代碼中添加事件處理程序,如下麵這段代碼:

<input  value="按鈕" type="button" >
<script>
    function showmsg(){
        alert("HTML添加事件處理");
      }
</script>

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

屬性綁定(DOM0級事件)

隻能綁定一個函數,在元素處於目標時觸發該事件

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

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

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

事件監聽函數(DOM2級事件)

當addEventListener的最後參數為false時,是在冒泡階段觸發。如果是true的話是在捕獲階段出發。attachEvent始終是冒泡階段觸發

element.addEventListener(<event-name>, <callback>, <use-capture>);

element.removeEventListener(<event-name>, <callback>, <use-capture>);

element.attachEvent(event, callback)(IE11以後用addEventLisener);

element.detachEvent(event, callback)(IE11以後用addEventLisener);

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

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

<input  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>

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

當同一個對象觸發多個方法的時候,後一個方法會把前一個方法覆蓋掉,也就是說,在對象的事件發生時,隻會執行最後綁定的方法。而用事件監聽則不會有覆蓋的現象,每個綁定的事件都會被執行

事件代理

原理:使用事件委托技術能讓你避免對特定的每個節點添加事件監聽器;相反,事件監聽器是被添加到它們的父元素上,利用冒泡的原理,把事件加到父級上,觸發執行效果

在父元素上綁定事件,監聽子元素的事件;主要用於子元素是新建元素或者子元素個數很多的情況下;這種方法可以提高性能,同時避免提前綁定元素事件而導致新建元素的事件沒有生效的結果

<ul> <li>11111111111111111111</li> </ul>

document.addEventListener('click', function (e) {
            console.log('document currentTarget: ' + e.currentTarget.nodeName);
            console.log('document target: ' + e.target.nodeName);
            if (e.target.nodeName === 'LI') {
                console.log('dom delegate: ' + e.eventPhase);
            }

            console.log(this);
 }, true);

使用事件委托對於web應用程序帶來的幾個優點:

1.可以大量節省內存占用,減少事件注冊

2.可以方便地動態添加和修改元素,不需要因為元素的改動而修改事件綁定

3.JavaScript和DOM節點之間的關聯變少了,這樣也就減少了因循環引用而帶來的內存泄漏發生的概率

缺點:

不是所有的事件都能冒泡的。blur、focus、load和unload不能像其它事件一樣冒泡。事實上blur和focus可以用事件捕獲而非事件冒泡的方法獲得(在IE之外的其它瀏覽器中)

在管理鼠標事件的時候有些需要注意的地方;如果你的代碼處理mousemove事件的話你遇上性能瓶頸的風險可就大了,因為mousemove事件觸發非常頻繁。而mouseout則因為其怪異的表現而變得很難用事件代理來管理。

事件冒泡和事件捕獲的流程與區別

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

1、事件捕獲階段;

2、處於目標階段;

3、事件冒泡階段。

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

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

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

這裏為什麼沒有布爾值呢?因為ie8以及更早的版本隻支持事件冒泡,所以最後一個參數默認的相當於false來處理

事件的傳播是可以阻止的:

在W3c中,使用stopPropagation()方法

在IE下設置cancelBubble = true;

在捕獲的過程中stopPropagation();後麵的冒泡過程也不會發生了~

阻止事件的默認行為,例如click 後的跳轉~

在W3c中,使用preventDefault()方法;

在IE下設置window.event.returnValue = false;

自定義事件

DOM3級還定義了自定義事件,自定義事件不是由DOM原生觸發的,它的目的是讓開發人員創建自己的事件。要創建的自定義事件可以由createEvent("CustomEvent");

返回的對象有一個initCustomEvent()方法接收如下四個參數

1)type:字符串,觸發的事件類型,自定義。例如 “keyDown”,“selectedChange”;

2)bubble(布爾值):標示事件是否應該冒泡

3)cancelable(布爾值):標示事件是否可以取消

4)detail(對象):任意值,保存在event對象的detail屬性中

可以像分配其他事件一樣在DOM中分派創建的自定義事件對象

最後更新:2017-04-29 00:00:48

  上一篇:go RDC到底是怎樣的一款產品?
  下一篇:go 4月28日雲棲精選夜讀:阿裏NASA計劃新科技“麒麟”露麵 打破能耗對數據中心製約