JavaScript與HTML的交互是經過事件實現的,事件表明文檔或瀏覽器窗口中某個有意義的時刻。javascript
可使用僅在事件發生時執行的監聽器(即處理程序)訂閱事件。=>觀察者模式 => 頁面行爲(JavaScript中定義)與頁面展現(HTML和CSS定義)的分離。html
最先的事件是爲了把某些表單處理工做從服務器轉移到瀏覽器上來。DOM2開始嘗試以符合邏輯的方式來標準化DOM事件。IE8是最後一個使用專有事件系統的主流瀏覽器。java
頁面哪一個部分擁有特定的事件呢?當你點擊一個按鈕時,實際上不光點擊了這個按鈕,還點擊了它的容器以及整個頁面。數組
事件流描述了頁面接收事件的順序。瀏覽器
IE支持事件冒泡流,Netscape Communicator支持事件捕獲流緩存
從最具體的元素開始觸發,而後向上傳播至沒有那麼具體的元素(document)。安全
點擊事件:被點擊的元素最早觸發click事件,而後click事件沿DOM樹一路向上,在通過的每一個節點上依次觸發,直至到達document對象。服務器
現代瀏覽器中的事件會一直冒泡到window對象。編輯器
最不具體的節點(document)最早收到事件,而最具體的節點最後收到事件。=>爲了在事件到達最終目標前攔截事件。ide
點擊事件:最早由document元素捕獲,而後沿DOM樹依次向下傳播,直至到達實際的目標元素。
現代瀏覽器都是從window對象開始捕獲事件。DOM2 Events規範規定的是從document開始。
因爲舊版本瀏覽器不支持,一般建議使用事件冒泡,特殊狀況下可使用事件捕獲。
DOM2 Events規範規定事件流分爲3個階段:事件捕獲、到達目標和事件冒泡。
在DOM事件流中,實際的目標在捕獲階段不會接收到事件。下一階段會在實際目標元素上觸發事件的「到達目標」階段,一般在事件處理時被認爲是冒泡階段的一部分;而後冒泡階段開始,事件反向傳播至文檔。
雖然DOM2 Events規範明確捕獲階段不命中事件目標,但現代瀏覽器都會在捕獲階段在事件目標上觸發事件。=> 在事件目標上有兩個機會來處理事件。
全部現代瀏覽器都支持DOM事件流,只有IE8及更早版本不支持。
capture phase | | / \ bubbling up -----------------| |--| |----------------- | element1 | | | | | | -------------| |--| |----------- | | |element2 \ / | | | | | -------------------------------- | | W3C event model | ------------------------------------------
事件是用戶或瀏覽器執行的某種動做。如click、load等。
爲響應事件而調用的函數被稱爲事件處理程序(或事件監聽器)。事件處理程序的名字以「on」開頭。
有多種方式能夠指定事件處理程序。
特定元素支持的每一個事件均可以使用事件處理程序的名字(onxxx)以HTML屬性的形式來指定。此時屬性的值必須是可以執行的JavaScript代碼。
由於屬性的值是JavaScript代碼,因此不能在未經轉義的狀況下使用HTML語法字符,如&、"、<和>。爲避免使用HTML實體,可使用單引號代替雙引號,或者使用\"。
在HTML中定義的事件處理程序能夠包含精確的動做指令,也能夠調用在頁面其餘地方定義的腳本。做爲事件處理程序執行的代碼能夠訪問全局做用域中的一切。
以這種方式指定的事件處理程序有一些特殊的地方:
這個動態建立的包裝函數,其做用域鏈被擴展了。=> document和元素自身的成員均可以被當成局部變量來訪問。這是經過使用with實現的。
// 實際上的包裝函數是onclick屬性的值 function () { with(document) { with(this) { // ... HTML事件處理程序屬性值 } } }
=> 事件處理程序能夠更方便地訪問本身的屬性(不用帶this.)
若是元素是一個表單輸入框,則做用域鏈中還會包含表單元素 => 事件處理程序的代碼能夠沒必要引用表單元素,而直接訪問同一表單中的其餘成員了(經過name屬性)。
在HTML中指定事件處理程序存在的問題:
時機問題。有可能HTML元素已經顯示在頁面上,但事件處理程序的代碼還沒法執行。=> 大多數HTML事件處理程序會封裝在try/catch塊中,以便在這種狀況下靜默失敗。
<input type="button" value="Click Me" onclick="try{doSomething();}catch(ex){}">
把一個函數賦值給(DOM元素的)一個事件處理程序屬性。=> 簡單
要使用JavaScript指定事件處理程序,必須先取得要操做對象的引用。
每一個元素(包括window和document)都有一般小寫的事件處理程序屬性。
賦值代碼運行以後纔會給事件處理程序賦值。
所賦函數被視爲元素的方法。=> 事件處理程序會在元素的做用域中運行,即this等於元素。
let btn = document.querySelector('#myBtn'); btn.onclick = function() { console.log(this.id); // "myBtn" }
以這種方式添加事件處理程序是註冊在事件流的冒泡階段的。
經過將事件處理程序屬性的值設置爲null,能夠移除經過DOM0方式添加的事件處理程序。(在HTML中指定的事件處理程序,也能夠經過JavaScript將相應屬性設置爲null來移除)
btn.onclick = null;
DOM2 Events爲事件處理程序的賦值和移除定義了兩個方法:addEventListener()和removeEventListener()。暴露在全部DOM節點上。
接收3個參數:事件名、事件處理函數和一個表示是否在捕獲階段調用處理函數的布爾值(默認值爲false,在冒泡階段調用)。
這個事件處理程序一樣在被附加到的元素的做用域中運行:this等於元素。
主要優點:能夠爲同一個事件添加多個事件處理程序。多個事件處理程序以添加順序來觸發。
經過addEventListener()添加的事件處理程序只能使用removeEventListener()並傳入與添加時一樣的參數來移除。(事件處理函數必須是同一個)
大多數狀況下,事件處理程序會被添加到事件流的冒泡階段,主要緣由是跨瀏覽器兼容性好。(除非須要在事件到達其指定目標以前攔截事件)
IE實現了與DOM相似的方法,attachEvent()和detachEvent()。
接收2個參數:事件處理程序的名字和事件處理函數。由於IE8及更早版本只支持事件冒泡,因此使用attachEvent()添加的事件處理程序會添加到冒泡階段。
在IE中使用attachEvent()與使用DOM0方式的主要區別在於事件處理程序的做用域。使用attachEvent()時,事件處理程序是在全局做用域中運行的,所以this等於window。
attachEvent()方法也能夠給一個元素添加多個事件處理程序。以添加它們的順序反向觸發。
使用attachEvent()添加的事件處理程序將使用detachEvent()來移除,只要提供相同的參數(處理函數是相同的函數引用)。
let btn = document.querySelector('#myBtn'); var handler = function() { console.log("Clicked"); }; btn.attachEvent("onclick", handler); btn.detachEvent("onclick", handler);
以跨瀏覽器兼容的方式處理事件。
本身編寫跨瀏覽器事件處理代碼主要依賴能力檢測。要確保最大兼容性,只要讓代碼在冒泡階段運行便可。
var EventUtil = { addHandler: function(element, type, handler) { if(element.addEventListener) { element.addEventListener(type, handler, false); } else if(element.attachEvent) { element.attachEvent("on"+type, handler); } else { // 默認DOM0方式 element["on"+type] = handler; } }, removeHandler: function(element, type, handler) { if(element.removeEventListener) { element.removeEventListener(type, handler, false); } else if(element.detachEvent) { element.detachEvent("on"+type, handler); } else { // 默認DOM0方式 element["on"+type] = null; } } }; // 使用 let btn = document.querySelector('#myBtn'); let handler = function() { console.log("Clicked"); }; EventUtil.addHandler(btn, "click", handler); EventUtil.removeHandler(btn, "click", handler);
沒有解決的存在的問題:
在DOM中發生事件時,全部相關信息(如事件目標元素、事件類型)都會被收集並存儲在一個名爲event的對象中。
在DOM合規的瀏覽器中,event對象是傳給事件處理程序的惟一參數。無論以哪一種方式(DOM0或DOM2)指定事件處理程序,都會傳入這個event對象。在經過HTML屬性指定的事件處理程序中,一樣可使用變量event引用事件對象。
全部事件對象包含的公共屬性和方法:
在事件處理程序內部,this始終等於currentTarget。this === event.currentTarget
。
若是事件處理程序直接添加在乎圖的目標,則this、currentTarget和target三者相等。
type屬性在一個處理程序處理多個事件時頗有用:根據事件類型,作出不一樣的響應。
preventDefault()可阻止特定事件的默認動做,如連接的默認行爲是被單擊時導航到href屬性指定的URL。任何可調用preventDefault()取消默認行爲的事件,其event對象的cancelable屬性都會設置爲true。
stopPropagation()用於當即阻止事件流在DOM結構中傳播,取消後續的事件捕獲或冒泡。
eventPhase屬性可用於肯定事件流當前所處的階段。若是事件處理程序在目標上被調用,則eventPhase等於2 => 雖然」到達目標「是在冒泡階段發生的,但eventPhase等於2。=> 當eventPhase等於2,this、currentTarget和target三者相等。
event對象只在事件處理程序執行期間存在,一旦執行完畢,就會被銷燬。
IE事件對象能夠基於事件處理程序被指定的方式以不一樣的方式來訪問。
全部IE事件對象都會包含的公共屬性和方法:
事件處理程序的做用域取決於指定它的方式,因此更好的方式是使用事件對象的srcElement屬性代替this。(DOM0方式下,this等於元素;attachEvent()方式下,this等於window)
與DOM不一樣,沒法經過JavaScript肯定事件是否能夠被取消。
cancelBubble屬性與stopPropagation()方法用途類似,但IE8及更早版本不支持捕獲階段,因此只會取消冒泡。
DOM事件對象中包含IE事件對象的全部信息和能力,只是形式不一樣。這些共性可以讓兩種事件模型之間的映射成爲可能。
var EventUtil = { addHandler: function(element, type, handler) { // ... }, removeHandler: function(element, type, handler) { // ... }, getEvent: function(event) { // IE事件中以DOM0方式指定事件處理程序時,event對象是window的一個屬性 return event ? event || window.event; }, getTarget: function(event) { return event.target || event.srcElement; }, preventDefault: function(event) { if(event.preventDefault) { event.preventDefault(); } else { event.returnValue = false; } }, stopPropagation: function(event) { // 可能會中止事件冒泡,也可能既會中止事件冒泡也中止事件捕獲 if(event.stopPropagation) { event.stopPropagation(); } else { event.cancelBubble = true; } } }; // 使用 let btn = document.querySelector('#myBtn'); btn.onclick = function(event) { event = EventUtil.getEvent(event); let target = EventUtil.getTarget(event); EventUtil.preventDefault(event); // 阻止事件的默認行爲 EventUtil.stopPropagation(event); // 阻止事件冒泡 };
所發生事件的類型決定了事件對象中會保存什麼信息。DOM3 Events定義的事件類型:
DOM3 Events在DOM2 Events基礎上從新定義了事件,並增長了新的事件類型。全部主流瀏覽器都支持DOM2 Events和DOM3Events。
不必定跟用戶操做有關。保留它們是爲了向後兼容。主要有如下幾種:
大多數HTML事件與window對象和表單控件有關。除了DOMActivate,其餘在DOM2 Events中都被歸爲HTML Events。(DOMActivate是UI事件)
頁面元素得到或失去焦點時觸發。能夠與document.hasFocus()和document.activeElement一塊兒爲開發者提供用戶在頁面中導航的信息。焦點事件有如下6種:
兩個主要事件是focus和blur,它們最大的問題是不冒泡。
當焦點從頁面中的一個元素A移到另外一個元素B上,會依次發生以下事件(測試,與書中不一致):
1)A:blur
2)A:focusout
3)B:focus
4)B:focusin
DOMFocusOut和DOMFocusIn未驗證
鼠標是用戶的主要定位設備。DOM3 Events定義了9種鼠標事件:
頁面中全部元素都支持鼠標事件。除了mouseenter和mouseleave,其餘鼠標事件都會冒泡,均可以被取消,這會影響瀏覽器的默認行爲。因爲事件之間存在關係,所以取消鼠標事件的默認行爲也會影響其餘事件。
雙擊鼠標主鍵會按以下順序觸發事件:
1)mousedown
2)mouseup
3)click
4)mousedown
5)mouseup
6)click
7)dblclick
click和dblclick在觸發前都依賴其餘事件觸發,mousedown和mouseup則不會受其餘事件影響。
IE8和更早的版本的實現中存在問題,會致使雙擊事件跳過第二次mousedown和click事件。
1)mousedown
2)mouseup
3)click
4)mouseup
5)dblclick
DOM3 Events中鼠標事件對應的類型是」MouseEvent「(單數形式)
鼠標事件還有一個名爲滾輪事件的子類別。滾輪事件只有一個事件mousewheel,對應鼠標滾輪或帶滾輪的相似設備上滾輪的交互。
鼠標事件event對象的一些屬性:
客戶端座標
注:客戶端座標不考慮頁面滾動
頁面座標
在頁面上的位置。表示事件發生時鼠標光標在頁面上的座標,經過event對象的pageX和pageY屬性獲取。
反映的是光標到頁面而非視口左邊與上邊的距離。
屏幕座標
鼠標光標在屏幕上的座標,經過event對象的screenX和screenY屬性獲取。
修飾鍵
有時要肯定用戶想實現的操做,還要考慮鍵盤按鍵的狀態。
鍵盤上的修飾鍵Shift、Ctrl、Alt和Meta(win的window鍵,mac的command鍵)常常用於修改鼠標事件的行爲。
4個屬性來表示這幾個修飾鍵的狀態:shiftKey、ctrlKey、altKey、metaKey。(被按下爲true,不然爲false)
如今瀏覽器支持全部4個修飾鍵,IE8及更早版本不支持metaKey屬性。
相關元素
對mouseover和mouseout事件而言,還存在與事件相關的其餘元素。
鼠標按鍵
對mousedown和mouseup事件來講,event對象上會有一個button屬性,表示按下或釋放的是哪一個按鍵。DOM爲button屬性定義了3個值:0-主鍵;1-中鍵(一般是滾輪鍵);2-副鍵。
IE8及更早版本也提供了button屬性,考慮了同時按多個鍵的狀況。
額外事件信息
DOM2 Events規範在event對象上提供了detail屬性,以給出關於事件的更多信息。對鼠標事件來講,detail包含一個數值,表示在給定位置上發生了多少次單擊(連續單擊)。每次單擊會加1。連續點擊中斷會重置爲0。
IE還爲每一個鼠標事件提供瞭如下額外信息:
滾輪mousewheel事件
在用戶使用鼠標滾輪時觸發,包括在垂直方向上任意滾動。會在任何元素上觸發,並(在IE8中)冒泡到document和(全部現代瀏覽器中)window。
event對象包含鼠標事件的全部標準信息,此外還有一個名爲wheelDelta的屬性。
多數狀況下只需知道滾輪滾動的方向,而這經過wheelDelta值的符號就能夠知道。(向前滾動一次+120,向後滾動一次-120)
觸摸屏設備
觸摸屏一般不支持鼠標操做。
無障礙問題
若是Web應用或網站要考慮殘障人士,特別是使用屏幕閱讀器的用戶,那麼必須當心使用鼠標事件(除了回車鍵能夠觸發click事件,其餘鼠標事件不能經過鍵盤觸發)。建議不要使用click事件以外的其餘鼠標事件向用戶提示功能或觸發代碼執行。=> 會嚴格妨礙盲人或視障用戶使用。
幾條使用鼠標事件時應該遵循的無障礙建議:
更多網站無障礙的信息,能夠參考WebAIM網站。
用戶操做鍵盤時觸發。很大程度上是基於原始的DOM0實現的。
DOM3 Events爲鍵盤事件提供了一個首先在IE9中徹底實現的規範,其餘瀏覽器也開始實現該規範,但仍存在不少遺留的實現。
包含3個事件:
全部元素都支持這些事件。但在文本框中輸入內容時最容易看到。
輸入事件只有一個:textInput。是對keypress事件的擴展,用於在文本顯示給用戶以前更方便地截獲文本輸入。會在文本被插入到文本框以前觸發。
注:鍵盤事件支持與鼠標事件相同的修飾鍵。
鍵盤事件event對象的一些屬性:
鍵碼keyCode
keydown和keyup事件,event對象的keyCode屬性會保存一個鍵碼。
對於字母和數字鍵,keyCode的值與大寫字母和數字的ASCII編碼一致。與是否按了Shift鍵無關。
DOM和IE的event對象都支持keyCode屬性
字符編碼charCode
keypress事件,意味着按鍵會影響屏幕上顯示的文本。對插入或移除字符的鍵,全部瀏覽器都會觸發keypress事件,其餘鍵則取決於瀏覽器。
event對象上的charCode屬性,只有發生keypress事件時這個屬性纔會被設置值(此時與keyCode屬性相等)。包含的是按鍵字符對應的ASCII編碼。
IE8及更早版本和Opera使用keyCode傳達字符的ASCII編碼。要以跨瀏覽器方式獲取字符編碼,首先要檢測charCode屬性是否有值,若是沒有再使用keyCode。
有了字母編碼,就可使用String.fromCharCode()方法將其轉換爲實際的字符了。
DOM3的變化
DOM3 Events規範並未規定charCode屬性,而是定義了key和char兩個新屬性。
key屬性用於替代keyCode,且包含字符串。按下字符鍵時,key等於文本字符;按下非字符鍵時,key的值是鍵名(如」Shift「或」ArrowDown「)
char屬性在按下字符鍵時與key相似,在按下非字符鍵時爲null。(測試Chrome中keypress和keydown的event對象此屬性都無)
IE支持key屬性但不支持char屬性。
Safari和Chrome支持keyIdentifier屬性(測試Chrome無此屬性)。對於字符鍵,keyIdentifier返回以」U+0000「形式表示Unicode值的字符串形式的字符編碼。
因爲缺少跨瀏覽器支持,不建議使用key、keyIdentifier和char。
DOM3 Events也支持一個名爲location的屬性,是一個數值,表示是在哪裏按的鍵。可能的值爲:0-默認鍵;1-左邊;2-右邊;3-數字鍵盤;4-移動設備(虛擬鍵盤);5-遊戲手柄。Safari和Chrome支持一個等價的keyLocation屬性(實現有問題)
沒有獲得普遍支持,不建議在跨瀏覽器開發時使用location屬性。
給event對象增長了getModifierState()方法,接收一個參數,一個等於Shift、Control、Alt、AltGraph或Meta的字符串,表示要檢測的修飾鍵。若是給定 的修飾鍵被按鈕,則返回true。(也可直接使用event對象的shiftKey、ctrlKey、altKey或metaKey屬性獲取)
輸入textInput事件
DOM3 Events規範新增,在字符被輸入到可編輯區域時觸發。
與keypress比對:1. keypress會在任何能夠得到焦點的元素上觸發,textInput只在可編輯區域上觸發;2. textInput只在有新字符被插入時纔會觸發,而keypress對任何可能影響文本的鍵都會觸發(包括退格鍵(Chrome裏測試不會觸發?))。3. 使用輸入法(搜狗)時,在觸發合成事件時不會觸發keypress,在compositionend觸發以前會先觸發textInput事件。4. 使用鍵盤輸入先觸發keypress,再觸發textInput。
該事件主要關注字符,event對象上有data屬性,爲被插入的字符(非字符編碼);還有一個inputMethod的屬性(Chrome中測試無此屬性打印爲undefined),表示向控件中輸入文本的手段,能夠輔助驗證
設備上的鍵盤事件(非鍵盤)
任天堂Wii
DOM3 Events中新增,用於處理一般使用IME輸入時的複雜輸入序列。IME可讓用戶輸入物理鍵盤上沒有的字符,一般須要按下多個鍵才能輸入一個字符,合成事件用於檢測和控制這種輸入。
合成事件有如下3種:
惟一增長的事件屬性是data:
測試獲得的觸發順序:
keydown -> ...start -> ...update -> ( (keyup) -> keydown -> ...update -> (keyup))(循環觸發) -> ...update(此時data與...end事件中的data一致) -> textInput -> ...end -> keyup
DOM2的變化事件(Mutation Events),在DOM發生變化時提供通知。
(已廢棄)
已經被Mutation Observers所取代(第14章)
HTML5中獲得瀏覽器較好支持的一些事件(規範未涵蓋)
contextmenu事件
單擊鼠標右鍵(Ctrl+單擊左鍵)。用於容許開發者取消默認的上下文菜單並提供自定義菜單。冒泡。
事件目標是觸發操做的元素,這個事件在全部瀏覽器中均可以取消(event.preventDefault()或event.returnValue設置爲false)。
一般經過onclick事件處理程序觸發隱藏(自定義菜單)。
beforeunload事件
在window上觸發。用於給開發者提供阻止頁面被卸載的機會。在頁面即將從瀏覽器中卸載時觸發。
不能取消,不然就意味着能夠把用戶永久阻攔在一個頁面上。
該事件會向用戶顯示一個確認框。用戶能夠點擊取消或者確認離開頁面。須要將event.returnValue設置爲要在確認框中顯示的字符串(對於IE和FF來講)(測試FF顯示的提示文字與returnValue屬性值無關),並將其做爲函數值返回(對於Safari和Chrome來講)(測試Chrome無返回值也無影響)
DOMContentLoaded事件
會在DOM樹構建完成後當即觸發,而不用等待圖片、JavaScript文件、CSS文件或其餘資源加載完成。(能夠在外部資源下載的同時指定事件處理程序,從而讓用戶可以更快地與頁面交互)
比對load事件:要等待不少外部資源加載完成。
須要給document或window添加事件處理程序(實際的事件目標是document,會冒泡到window)。
一般用於添加事件處理程序或執行其餘DOM操做。這個事件始終在load事件以前觸發。
對於不支持DOMContentLoaded事件的瀏覽器,可使用超時爲0的setTimeout()函數,經過其回調來設置事件處理程序。本質上是在當前JavaScript進程執行完畢後當即執行這個回調。(與DOMContentLoaded觸發時機一致無絕對把握,最好是頁面上的第一個超時代碼)
readystatechange事件
IE首先定義。用於提供文檔或元素加載狀態的信息,但行爲有時不穩定。
event.target或其餘支持readystatechange事件的對象都有一個readyState屬性,該屬性可能爲如下5個值:
並不是全部對象都會經歷全部readyState階段(Chrome測試document只經歷了兩個階段:interactive和complete)
值爲」interactive「的readyState階段,時機相似於DOMContentLoaded。進入交互階段,意味着DOM樹已加載完成。(此時圖片和其餘外部資源不必定都加載完成了)。
與load事件共同使用時,這個事件的觸發順序不能保證。interactive和complete的順序也不是固定的,爲了搶到較早的時機,須要同時檢測交互階段和完成階段(能夠保證儘量接近使用DOMContentLoaded事件的效果)。
pageshow與pagehide事件
FF和Opera開發的一個名爲往返緩存(bfcache,back-forward cache)的功能,旨在使用瀏覽器」前進「和」後退「按鈕時加快頁面之間的切換。不只存儲頁面數據,也存儲DOM和JavaScript狀態,其實是把整個頁面都保存在內存裏。
若是頁面在緩存中,導航到這個頁面時就不會觸發load事件。
pagehide:在頁面從瀏覽器中卸載後,在unload事件以前觸發。事件目標是document,但事件處理程序必須添加到window上。event對象中的persisted屬性爲布爾值,表示頁面在卸載後是否保存在往返緩存中。
註冊了onunload事件處理程序的頁面會自動排除在往返緩存以外(測試beforeunload也會影響),由於onunload的典型場景就是撤銷onload事件發生時所作的事情,若是使用往返緩存,下一次頁面顯示時就不會觸發onload事件,這可能致使頁面沒法使用。
hashchange事件
用於在URL散列值(#後面的部分)發生變化時通知開發者。
事件處理程序必須添加給window。event對象有兩個新屬性:oldURL和newURL,分別保存變化先後的URL,包含散列值的完整URL。若是想肯定當前的散列值,最好使用location對象。
智能手機和平板計算機=>交互的新方式
用於肯定用戶使用設備的方式。
orientationchange事件
蘋果,移動Safari瀏覽器。判斷用戶的設備是處於垂直模式仍是水平模式。window.orientation屬性,有3種值:0-垂直模式,90-左轉水平模式(Home鍵在右),-90-右轉水平模式(Home鍵在左)。當屬性值改變就會觸發該事件。
全部iOS設備都支持該事件和該屬性。(測試鎖定豎屏=>不會改變)
被認爲是window事件,也可給body元素添加onorientationchange屬性來指定事件處理程序。
deviceorientation事件
DeviceOrientationEvent規範定義的事件。
若是能夠獲取設備的加速計信息,且數據發生了變化,就會在window上觸發。只反應設備在空間中的朝向,與移動無關。
設備自己處於3D空間,x軸方向爲從設備左側到右側,y軸方向爲從設備底部到上部,z軸方向爲從設備背面到正面。
event對象包含各個軸相對於設備靜置時座標值的變化,主要有5個屬性:
測試iPhone8(iOS11.4.1)平放在桌面上也一直監聽到變更(?),測試Android(一加三)平放在桌面上後不會變更
devicemotion事件
DeviceOrientationEvent規範定義的事件。
用於提示設備實際上在移動,而不只僅是改變了朝向。event對象包含的額外屬性:
若是沒法提供acceleration、accelerationIncludingGravity、rotationRate信息,則屬性值爲null。=> 使用以前必須先檢測
測試iPhone8(iOS11.4.1)平放在桌面上也一直監聽到變更,測試Android(一加三)平放在桌面上也一直監聽到變更
只適用於觸屏設備。
Webkit爲Android定製了不少專有事件,成爲了事實標準,並被歸入W3C的Touch Events規範。
觸摸事件
以下幾種:
都會冒泡,均可以被取消。不屬於DOM規範,瀏覽器以兼容DOM的方式實現它們。每一個觸摸事件的event對象都提供了鼠標事件的公共屬性,另外提供如下3個屬性用於跟蹤觸點:
每一個Touch對象包含一些屬性,可用於追蹤屏幕上的觸摸軌跡。(針對一個觸點)touchend事件觸發時touches集合中什麼也沒有,這是由於沒有滾動的觸點了。
當手指點觸屏幕上的元素時,依次觸發的事件(測試與書本不一致):
1)touchstart
2)touchend
3)mousemove
4)mousedown
5)mouseup
6)click
手勢事件
iOS2.0中的Safari中增長。在兩個手指觸碰屏幕且相對距離或旋轉角度變化時觸發。有以下3種:
都會冒泡。
只有在兩個手指同時接觸事件接收者時(目標元素邊界之內),這些事件纔會觸發。
觸摸事件和手勢事件存在必定的關係。
每一個手勢事件的event對象都包含全部標準的鼠標事件屬性,新增了兩個屬性是rotation和scale。
rotation:表示手指變化旋轉的度數,負值表示逆時針旋轉,正值表示順時針旋轉(從0開始);
scale:表示兩指之間距離變化(對捏)的程度,開始時爲1,而後隨着距離增大或縮小相應地增大或縮小。
觸摸事件也會返回rotation和scale屬性,但只在兩個手指觸碰屏幕時纔會變化。
參考書本
在JavaScript中,頁面中事件處理程序的數量與頁面總體性能直接相關。
首先,每一個函數都是對象,都佔用內存空間;其次,爲指定事件處理程序所需訪問DOM的次數會先期形成整個頁面交互的延遲。
改善頁面性能?
」過多事件處理程序「的解決方案是使用事件委託。
利用事件冒泡,能夠只使用一個事件處理程序來管理一種類型的事件。只要給全部元素(須要處理某種事件的元素)共同的祖先節點添加一個事件處理程序,就能夠解決問題(根據target判斷進行不一樣的處理)。=> 只訪問了一個DOM元素和添加了一個事件處理程序。 => 佔用內存更少,全部使用按鈕的事件(大多數鼠標事件和鍵盤事件)都適用於這個解決方案。
只要可行,就應該考慮只給document添加一個事件處理程序,經過它處理頁面中全部某種類型的事件。優勢以下:
最適合使用事件委託的事件包括:click、mousedown、mouseup、keydown和keypress。
把事件處理程序指定給元素後,在瀏覽器代碼和負責頁面交互的JavaScript代碼之間就創建了聯繫。這種聯繫創建得越多,頁面性能就越差。除了使用事件委託減小這種聯繫外,還應及時刪除不用的事件處理程序。
不少Web應用性能不佳都是因爲無用的事件處理程序長駐內存致使的。緣由以下:
刪除帶有事件處理程序的元素。如使用方法removeChild()或replaceChild()刪除節點,或使用innerHTML總體替換頁面的某一部分。=> 被刪除的元素上如有事件處理程序,就不會被垃圾收集程序正常清理。(特別是IE8及更早版本,元素的引用和事件處理程序的引用)
若是知道某個元素會被刪除,那麼最好在刪除它以前手工刪除它的事件處理程序(或者不直接給它添加事件處理程序,使用事件委託)。=>確保內存被回收,元素也能夠安全地從DOM中刪掉。
注意:在事件處理程序中刪除元素會阻止事件冒泡。只有事件目標仍然存在於文檔中時,事件纔會冒泡。
頁面卸載致使內存中殘留引用。事件處理程序沒有被清理,會殘留在內存中。
最好在onunload事件處理程序中趁頁面還沒有卸載先刪除全部事件處理程序。=> 使用事件委託的優點:事件處理程序不多。
一般事件都是由用戶交互或瀏覽器功能觸發。
能夠經過JavaScript在任什麼時候候觸發任意事件 => 在測試Web應用時特別有用
DOM3規範指明瞭模擬特定類型事件的方式。
步驟:
使用document.createEvent()方法建立一個event對象。
createEvent()方法接收一個參數,一個表示要建立事件類型的字符串。DOM2是英文複數形式,DOM3中是英文單數形式。可用值爲如下之一:
使用事件相關的信息來初始化
每種類型的event對象都有特定的方法,取決於調用createEvent()時傳入的參數
觸發事件
事件目標調用dispatchEvent()方法。該方法存在於全部支持事件的DOM節點上。
接收一個參數,即要觸發事件的event對象
不一樣事件類型的模擬:
鼠標事件
全部鼠標事件均可以在DOM合規的瀏覽器中模擬出來
鍵盤事件
DOM3 Events中廢棄了keypress事件,所以只能經過上述方式模擬keydown和keyup事件。
在使用document.createEvent("KeyboardEvent")
以前,最好檢測一下瀏覽器對DOM3鍵盤事件的支持狀況document.implementation.hasFeature("KeyboardEvents", "3.0")
。
測試Chrome,調用initKeyboardEvent()方法傳入的key和modifier參數與在事件處理程序中打印出來的屬性不一致,可使用new KeyboardEvent()
(參數與在事件處理程序中打印出的一致),另,兩種模擬都不會使文本框中有內容
FF限定:
測試:ff(88.0)顯示不支持 Uncaught DOMException: Operation is not supported
其餘不支持鍵盤事件的瀏覽器:
必須使用通用事件而不是用戶界面事件,由於用戶界面事件不容許直接給event對象添加屬性
其餘事件
HTML事件:
測試:模擬focus,能監聽到事件,可是沒有光標
自定義DOM事件
DOM3新增自定義事件類型。不觸發原生DOM事件。
在IE8及更早版本中模擬事件。
步驟:
IE支持的全部事件均可以經過相同的方式來模擬。
最多見的事件是在DOM3 Events規範或HTML5中定義的。
須要考慮內存與性能問題:
限制頁面中事件處理程序數量。=> 避免佔用過多內存致使頁面響應慢,清理起來更方便