JAVASCRIPT事件詳解-------原生事件基礎....


javaScirpt事件詳解-原生事件基礎(一)

 

事件

JavaScript與HTML之間的交互是通過事件實現的。事件,就是文檔或瀏覽器窗口中發生的一些特定的交互瞬間,通過監聽特定事件的發生,你能響應相關的操作。圖片引用:UI Events

事件流

主要是當時的IE團隊提出的事件流逝是事件冒泡流,而Netscape提出的是事件捕獲流, 可以使用DOM2級定義的addEventListener()方法來處理在冒泡或者捕獲階段調用事件處理程序。

事件冒泡

即事件開始時由最具體的元素(文檔中嵌套最深的節點)接收,然后逐級向上傳播到較為不具體的節點。 1

事件捕獲

即最外層的元素更早接收到事件,而最具體的元素應該最后接收到事件。事件捕獲的用意在於在事件到達預定目標之前捕獲它。 2

DOM事件流

而“DOM2級事件”規定的事件流包括三個階段:事件捕獲階段,處於目標階段和事件冒泡階段。首先發生的是事件捕獲,然后是實際的目標接收到事件,最后一個階段是冒泡階段。 3

addEventListener函數接收三個參數,要處理的事件名、作為事件處理程序的函數和一個布爾值,最后的布爾值如果是true,表示在不回階段調用事件處理程序;如果是false,表示在冒泡階段調用事件處理程序。

事件捕獲:

//html <!DOCTYPE html> <html> <head> <title></title> </head> <body> <div class="a"> <div class="b"> <button class="c">click</button> </div> </div> </body> </html> var $body = document.querySelector("body"), $a = document.querySelector(".a"), $b = document.querySelector(".b"), $c = document.querySelector(".c"); $body.addEventListener("click",function(){ console.log(this); },true); $a.addEventListener("click",function(){ console.log(this); },true); $b.addEventListener("click",function(){ console.log(this); },true); $c.addEventListener("click",function(){ console.log(this); },true);

單擊button,則 4

事件冒泡:

$body.addEventListener("click",function(){ console.log(this); },false); $a.addEventListener("click",function(){ console.log(this); },false); $b.addEventListener("click",function(){ console.log(this); },false); $c.addEventListener("click",function(){ console.log(this); },false);

單擊button,則 5

上述代碼在IE9和其他現代瀏覽器都支持(測試頁)。IE8及更早版本不支持DOM事件流只有事件冒泡。所以我們有兩個階段可以在目標對象上操作事件,但為了兼容性考慮,一般用冒泡的情況比較多。

事件處理程序

事件是用戶或瀏覽器自身執行的某種動作,而響應某個事件的函數就叫做事件處理程序(或事件偵聽器)

HTML事件處理程序

即內聯式處理函數,以"on"開頭:

<button onclick="alert(this)"></button>

雖然方便,但有很大問題,首先,存在時差問題,因為用戶可能會在HTML元素一出現在頁面上就觸發相應的事件,但當時的事件處理程序有可能尚不具備執行條件;另一個缺點是:這樣擴展事件處理程序的作用域鏈在不同瀏覽器會導致不同結果;而最后的缺點則是HTML與JavaScript代碼緊密耦合,如果要更換事件處理程序,就要改動兩個地方。

DOM0級事件處理程序

通過JavaScript指定事件處理程序的傳統方式,就是將一個函數賦值給一個事件處理程序屬性。 每個元素(包括window和docuemnt)都有自己的事件處理程序屬性,這些屬性通常全部小寫:

var btn = document.getElementById('myBtn'); btn.onclick = function(){ alert("Clicked"); }

以這種方式添加的事件處理程序會在事件流的冒泡階段被處理。

DOM2級事件處理程序

“DOM2級事件”定義了兩個方法,用於處理指定和刪除事件處理程序的操作:addEventListener()和removeEventListener()。所有DOM節點中都包含這兩個方法,在上面的事件捕獲和冒泡有用到。使用DOM2級方法添加事件處理程序的主要好處是可以添加多個事件處理程序。

IE事件處理程序

IE實現的方法是:attachEvent()和detachEvent()。這兩個方法接收相同的兩個參數:事件處理程序名稱與事件處理程序函數。通過attachEvent()添加的事件處理程序都會被添加到冒泡階段:

var btn = document.getElementById("myBtn"); btn.attachEvent("onclick",function(){ alert("Clicked"); })

這里的參數中表行為的是onclick而非DOM的addEventListener()方法中的click,在IE中使用attachEvent()與使用DOM0級方法的主要區別在於事件處理程序的作用域,在使用DOM0級方法的情況下,事件處理程序會在其所屬元素的作用域內運行;在使用attachEvent()方法的情況下,事件處理程序會在全局作用域中運行,因此this等於window

var btn = document.getElementById("myBtn"); btn.attachEvent('onclick',function(){ alert(this === window);// true });

事件對象

在觸發DOM上的某個事件時,會產生一個事件對象event,所有瀏覽器都支持event對象,但支持方式不同。

DOM中的事件對象

event對象包含與創建它的特定事件有關的屬性和方法。觸發的事件類型不一樣,可用的屬性和方法也不一樣。不過,所有事件都有下表的成員屬性。

屬性/方法 類型 讀/寫 說明
bubbles boolean 只讀 表明事件是否冒泡
cancelable boolean 只讀 表明是否可以取消事件的默認行為
currentTarget element 只讀 其事件處理程序當前正在處理事件的那個元素
defaultPrevented boolean 只讀 為true表示已經調用了preventDefault()DOM3新增
datail integer 只讀 與事件相關的細節信息
eventPhase integer 只讀 調用事件處理程序的階段:1表示捕獲階段,2表示處於目標 3表示冒泡階段
preventDefault() function 只讀 取消事件的默認行為。如果cancelable是true,則可以使用這個方法
stopImmediatePropagation() function 只讀 取消事件的進一步捕獲或冒泡,同時阻止任何事件處理程序被調用(DOM3級新增)
stopPropagation() function 只讀 取消事件的進一步捕獲或冒泡,如果bubbles為true,則可以使用這個方法
target element 只讀 事件的目標
isTrusted boolean 只讀 返回一個布爾值,表明當前事件是否是由用戶行為觸發,還是由一個腳本生成的
type string 只讀 被觸發的事件的類型
view AbstractView 只讀 與事件關聯的抽象視圖。等同於發生事件的window對象

更詳細的文檔可以看 這里

在事件處理程序內部,對象this始終等於currentTarget的值,而target則只包含事件的實際目標。如果直接將事件處理程序指定給了目標元素,則this,currentTarget和target包含相同的值。

根據event所擁有的屬性,就可以更加細致的操作事件。在w3c的這篇Events中,我們可以知道哪些事件可以冒泡. 首先是冒泡事件,如果只需要在具體節點觸發,而不冒泡到包裹層中,則可以使用與冒泡行為相關的一系列屬性,舉例:

<div class="a"> <a href="http://www.cnblogs.com"></a> </div>

在這個div中,如果div和a都有監聽點擊事件,那么在點擊a標簽的時候(默認事件流在已過捕獲階段),會先觸發a的點擊事件,然后是div的點擊事件,最后是a標簽的默認事件。如果不想冒泡,也就是說點擊a時只觸發a的點擊事件,則可以使用stopPropagation()方法:

var $a = document.querySelector("a"); $a.addEventListener("click",function(event){ if(event.bubbles){ event.stopPropagation(); } });

也可以在處理程序里直接刪除節點,也能阻止冒泡。 當然,有時我們不希望跳轉頁面,而是執行自定義的腳本,那就可以使用preventDefault()方法:

var $a = document.querySelector("a"); $a.addEventListener("click",function(event){ if(event.bubbles){ event.preventDefault(); // do something } });

有時我們可能會接手他人的代碼,在不了解具體代碼的情況下,如果只是單個獨立事件需要修改,則可以在運行老的js代碼之前,使用stopPropagation()方法。

$a.addEventListener('click',function(event){ event.preventDefault(); event.stopImmediatePropagation(); // do something }) $a.addEventListener("click",function(event){ alert("這是a標簽"); });

當然,冒泡並不是說是一件壞事,因為場景很多變,在某些場景下,冒泡也是很有用的,比如說事件代理(delegation)。 有時我們需要對生成的節點附加操作,event總是需要先找到element,再進行注冊,才可以進行事件監聽,那么對於這些生成的節點來說,當然可以在生成之后再次對該節點重新注冊事件。但如果是生成了同一個標記的節點呢? 那么我們不僅需要把之前注冊的事件remove,還需要重新綁定之前的標記,否則會二次觸發。這時候事件代理 就可以解決這一類問題。根據DOM事件流,我們可以知道,在節點冒泡時,可以一直往上冒泡,所以,我們完全可以把事件代理給點擊節點的父節點來做,根據event.target屬性,我們可以知道指向觸發事件的對象到底是誰,也因此,不用再使用繁瑣的重新注冊事件,就可以直接操作子元素。像jQuery,Zepto中都有關於事件代理的處理方法,后篇會繼續涉及到。

$div.addEventListener("click",function(event){ alert("這是外層"); if(event.target) { event.target.style.visibility = 'hidden'; } });

冒泡也會有副作用,mouseout事件會導致離開內部節點時提前觸發,為此,jQuery自定義了mouseenter和mouseleave事件,Zepto也有相應的事件。 只有在事件處理程序執行期間,event對象才會存在;一旦事件處理程序執行完成,event對象就會被銷毀(閉包)

IE中的事件對象

在IE中訪問event,特別是IE6~8尤其注意,在使用DOM0級方法添加事件處理程序時,event對象作為window對象的一個屬性存在。

var btn = document.getElementById('a'); btn.onclick = function(){ var event = window.event; alert(event.type); //"click" }

而IE中的event對象都會包含下表的屬性和方法:

屬性/方法 類型 讀/寫 說明
cancelBubble Boolean 讀/寫 默認值為false,但將其設置為true就可以取消事件冒泡(與DOM中的stopPropagation()方法的作用相同)
returnValue Boolean 讀/寫 默認值為false,但將其設置為false就可以取消事件的默認行為(與DOM中的preventDefault()方法的作用相同)
srcElement Element 只讀 事件的目標(與DOM中的target屬性相同)
type String 只讀 被觸發的事件的類型

事件類型

不表

事件模擬

結合jQuery和Zepto源碼總結。

部分用例:event

長路漫漫,與君共勉
如果您看完本篇文章感覺不錯,請點擊一下右下角的 推薦來支持一下博主,謝謝!
 
分類: javaScript
標簽: javascript
---------------------->此文轉載!


免責聲明!

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



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