每一個事件觸發時,都會產生一個與之對應的事件物件 event
,其中包含了觸發事件的元素、鍵盤滑鼠的狀態、位置等等內容。
每當使用者觸發一個事件後,JS 就會自動生成一個 event
物件,根據觸發事件的不同,這個物件包含的內容也不同,比如通過滑鼠觸發點選事件,會產生一個 MouseEvent
物件,其中包含了滑鼠的位置等內容;通過鍵盤觸發事件,會產生一個 KeyboardEvent
物件其中包含按鍵相關的資訊。
event
物件代表事件的狀態,比如觸發事件的元素、鍵盤按鍵的狀態、滑鼠的位置、滑鼠按鍵的狀態等等;event
物件是一個隱式引數,並且只在事件發生的過程中才有效;event
物件根據觸發方式的不同會具有不同的屬性,也就是說某些屬性只對特定事件有效,但所有內容都是繼承自 Event
物件;event
物件在 IE
與 Chrome
等瀏覽器表現不盡相同,例如說 event.target
表示觸發事件的元素,在 IE
中需要使用 event.srcElement
獲取;
Event
物件本身就是一個建構函式,可以用來生成新的範例。
event = new Event(type, options);
Event
建構函式接受兩個引數。第一個引數type
是字串,表示事件的名稱;第二個引數options
是一個物件,表示事件物件的設定。該物件主要有下面兩個屬性。
bubbles
:布林值,可選,預設為false,表示事件物件是否冒泡。
cancelable
:布林值,可選,預設為false,表示事件是否可以被取消,即能否用Event.preventDefault()
取消這個事件。一旦事件被取消,就好像從來沒有發生過,不會觸發瀏覽器對該事件的預設行為。
var ev = new Event( 'look', { 'bubbles': true, 'cancelable': false } ); document.dispatchEvent(ev);
上面程式碼新建一個look
事件範例,然後使用dispatchEvent
方法觸發該事件。
注意,如果不是顯式指定bubbles
屬性為true
,生成的事件就只能在「捕獲階段」觸發監聽函數。
// HTML 程式碼為 // <div><p>Hello</p></div> var div = document.querySelector('div'); var p = document.querySelector('p'); function callback(event) { var tag = event.currentTarget.tagName; console.log('Tag: ' + tag); // 沒有任何輸出 } div.addEventListener('click', callback, false); var click = new Event('click'); p.dispatchEvent(click);
上面程式碼中,p
元素髮出一個click
事件,該事件預設不會冒泡。div.addEventListener
方法指定在冒泡階段監聽,因此監聽函數不會觸發。如果寫成div.addEventListener('click', callback, true)
,那麼在「捕獲階段」可以監聽到這個事件。
另一方面,如果這個事件在div元素上觸發。
div.dispatchEvent(click);
那麼,不管div
元素是在冒泡階段監聽,還是在捕獲階段監聽,都會觸發監聽函數。因為這時div
元素是事件的目標,不存在是否冒泡的問題,div
元素總是會接收到事件,因此導致監聽函數生效。
我們在前面提到,根據觸發方式的不同 event
物件會具有不同的屬性,我們可以將其大體分為四部分:
通用屬性 (無論是通過鍵盤還是滑鼠觸發都擁有的屬性)
bubbles
事件是否會冒泡,布林值;
cancelable
事件是否具有預設行為,布林值;
預設行為指的是瀏覽器中規定的一些行為,比如 <a>
標籤點選後會跳轉連結,<form>
標籤內按回車會自動提交等等。
currentTarget
事件處理程式當前正在處理事件的那個元素,返回一個 Element
物件;
defaultPrevented
事件是否取消了預設行為,布林值;
detail
返回一個包含事件詳細資訊的數位
在 click
、 mousedown
和 mouseup
事件中,該數位表示當前的點選次數, dblclick
事件中,該數位一直為 2 。在鍵盤事件和滑鼠經過事件中,該數位一直為0。
eventPhase
返回一個代表事件處理程式發生時所在階段的數位;
0表示當前階段未發生其他事件;1表示當前事件在捕獲階段發生;2表示當前事件處於目標階段;3表示當前事件處於冒泡階段;
isTrusted
表示該事件是由使用者行為觸發的,還是由 JS 程式碼觸發的,布林值;
當事件是由使用者行為(點選等)觸發時,值為 true
,當事件是通過 EventTarget.dispatchEvent()
派發的時候,這個屬性的值為 false
。
<ul> <li>列表1</li> <li>列表2</li> <li>列表3</li> <li>列表4</li></ul><script> document.querySelector('ul').addEventListener("click", fn1, true) document.querySelector('ul').addEventListener("click", fn1, false) document.querySelector("li").addEventListener("click", fn1, true) function fn1() { console.log(this); // 列印當前事件物件 console.log(event.eventPhase); // 列印 }</script>
點選列表1後,控制檯列印如下結果:
target
返回觸發該事件的目標節點,返回一個 Element
物件;
target
並不一定與 this
指向相同,this
指向的是當前發生事件的元素,而 target
指向的是觸發該事件的元素,可以將上方程式碼中的 console.log(event.eventPhase);
換成 console.log(event.target);
來具體體驗一下兩者的不同。
在 IE
瀏覽器中應使用 srcElement
來代替 target
。
type
返回觸發的事件名稱,例 click
,keydown
等;
滑鼠屬性
button
當事件被觸發時,哪個滑鼠按鈕被點選;clientX
當事件被觸發時,滑鼠指標的 x 軸座標;clientY
當事件被觸發時,滑鼠指標的 y 軸座標;screenX
當事件被觸發時,滑鼠指標的 x 軸座標;screenY
當事件被觸發時,滑鼠指標的 y 軸座標;鍵盤屬性
altKey
當事件被觸發時,「Alt」 是否被按下;ctrlKey
當事件被觸發時,「Ctrl」 是否被按下;metaKey
當事件被觸發時,「meta」 是否被按下;shiftKey
當事件被觸發時,「Shift」 是否被按下;Location
返回按鍵在裝置上的位置;charCode
當事件被觸發時,觸發鍵值的字母程式碼;key
按下按鍵時返回按鍵的識別符號;keyCode
返回 keypress
事件觸發的鍵的值的字元程式碼,或者 keydown
或 keyup
事件的鍵的程式碼;which
返回 keypress
事件觸發的鍵的值的字元程式碼,或者 keydown
或 keyup
事件的鍵的程式碼;relatedTarget
返回與事件的目標節點相關的節點。IE屬性
cancelBubble
如果想阻止事件冒泡,必須把該屬性設為 true
;fromElement
對於 mouseover
和 mouseout
事件,fromElement
參照移出滑鼠的元素;returnValue
等同於 defaultPrevented
;srcElement
等同於 target
;toElement
對於 mouseover
和 mouseout
事件,該屬性參照移入滑鼠的元素;x
事件發生的位置的 x 座標;y
事件發生的位置的 y 座標;initEvent()
初始化新建立的 Event
物件的屬性;preventDefault()
阻止觸發事件元素的預設行為;stopPropagation()
阻止事件冒泡; 如果想要阻止事件元素的預設行為,例如點選 <a>
標籤時執行點選事件,不要跳轉連結,需要在事件處理程式中呼叫 preventDefault
方法:
<a href="http://baidu.com">百度一下,你就知道</a> <script> document.querySelector("a").onclick = function () { event.preventDefault(); // do something } </script>
如果想要阻止事件冒泡,例如點選子元素標籤時執行子元素的點選事件,而不想要執行父級元素的事件處理程式,則需要呼叫 stopPropagation
方法:
<ul> <li>不要觸發 ul 的點選事件處理程式</li> </ul> <script> document.querySelector("ul").onclick = function () { alert("事件冒泡,觸發 ul 的點選事件") } document.querySelector("li").onclick = function () { event.stopPropagation(); // do something } </script>
其他相關方法
addEventListener()
給目標元素註冊監聽事件;createEvent()
建立一個 Event
物件;dispatchEvent()
將事件傳送到目標元素的監聽器上;handleEvent()
把任意物件註冊為事件處理程式;initMouseEvent()
初始化滑鼠事件物件的值;initKeyboardEvent()
初始化鍵盤事件物件的值;initMutationEvent()
初始變動事件和 HTML
事件物件的值;initCustomEvent()
初始自定義事件物件的值;removeEventListener()
刪除目標元素上的某個監聽事件;另外關於 createEvent
方法,根據傳入引數的不同,會返回不同的 event
物件:
MouseEvents
建立滑鼠事件物件,返回的物件中包含 initMouseEvent()
方法;KeyboardEvent
建立鍵盤事件物件,返回的物件中包含 initKeyEvent()
方法;KeyEvents
在 firefox
中建立鍵盤事件物件需要傳入該引數;MutationEvents
模擬變動事件和 HTML 事件的事件物件,返回的物件中包含 initMutationEvent
方法;CustomEvent
建立自定義事件物件,返回的物件中包含 initCustomEvent()
方法; 我們可以通過 createEvent()
方法可以建立一個新的 event
物件,藉助 initMouseEvent()
方法來對這個滑鼠事件物件的值進行初始化,該方法接受十五個引數,分別與滑鼠事件中的各個屬性一一對應,按照 type
、bubbles
、cancelable
、view
、detail
、screenX
、screenY
、clientX
、clientY
、ctrlKey
、altKey
、shiftKey
、、metaKey
、button
、relatedTarget
的順序傳入即可:
var oBtn = document.querySelector("button"); // 為 button 繫結事件處理程式 oBtn.addEventListener("click", function () { console.log(event); }) var event = document.createEvent("MouseEvents"); // 通過 initMouseEvent() 方法初始化滑鼠事件的 event 物件 event.initMouseEvent("click", true, true, document.defaultView, 0, 0, 0, 0, 0, false, false, false, false, 0, null); // 通過 dispatchEvent() 方法來觸發 oBtn 上繫結的點選事件,此時瀏覽器列印的 event 物件為自定義的 event oBtn.dispatchEvent(event);
初始化事件物件時,最重要的是前四個引數,因為瀏覽器在觸發事件時,這四個引數是必須的,而剩餘的引數只有在事件處理程式中才會被使用,target
會在執行 dispatchEvent
方法時自動賦值;
同樣需要先使用 createEvent()
方法可以建立一個新的 event
物件,但需要使用 initKeyEvent
來對鍵盤事件物件的值進行初始化,該方法接收八個引數,分別於鍵盤事件物件中的各個屬性一一對應,按照 type
、bubbles
、cancelable
、view
、key
、location
、modifiers
、repeat
的順序傳入即可。但在 firefox
中,需要按照 type
、bubbles
、cancelable
、view
、ctrlKey
、altKey
、shiftKey
metaKey
keyCode
charCode
` 的順序傳入十個引數
document.onkeydown = function () { console.log(event); } var event = document.createEvent("KeyboardEvent"); event.initKeyboardEvent("keydown", false, false, document.defaultView, "a", 0, "Shift", 0); document.dispatchEvent(event);
如果想要模擬其他事件,諸如 submit
、focus
等 HTML
和變動事件,則需要通過 MutationEvents
方法來建立事件,通過 initEvent
方法來進行初始化,按照type
、bubbles
、cancelable
、relatedNode
、preValue
、newValue
、attrName
、attrChange
的順序傳入引數。
<input type="text"> <script> var oInput = document.querySelector("input"); oInput.addEventListener("focus", function () { this.style.background = "#ccc" }) var event = document.createEvent("HTMLEvents"); event.initEvent("focus", true, false); oInput.dispatchEvent(event); </script>
自定義事件不是由 DOM 原生觸發的,它的目的是讓開發人員建立自己的事件。要建立新的自定義事件,可以呼叫 createEvent("CustomEvent")
,返回的物件有一個名為 initCustomEvent()
的方法,接收 type
、bubbles
、cancelable
、detail
四個引數。
var oInput = document.querySelector("input"); oInput.addEventListener("myEvent", function () { console.log(event); }) var event = document.createEvent("CustomEvent"); event.initCustomEvent("myEvent", true, false, "自定義事件myEvent"); oInput.dispatchEvent(event);
上方程式碼建立了一個自定義事件,事件名為 myEvent
, 該事件可以向上冒泡,不可以執行在瀏覽器中的預設行為, detail
屬性的值為 自定義事件myEvent
,可以在繫結該事件的元素或者元素的父級元素上繫結事件處理程式來檢視 event
物件。
主要考慮到 IE
瀏覽器與 Chrome
等瀏覽器事件物件的區別,針對下面四個屬性,需要進行特殊處理:
獲得 event
物件var event = event || window.event;
獲得 target
物件var target = event.target || event.srcElement;
阻止瀏覽器預設行為event.preventDefault ? event.preventDefault() : (event.returnValue = false);
阻止事件冒泡event.stopPropagation ? event.stopPropagation() : (event.cancelBubble = true);
【相關推薦:】
以上就是深入解析JS中的事件物件Event的詳細內容,更多請關注TW511.COM其它相關文章!