以前寫過一篇瀏覽器事件的相關操做和事件運行的原理——JavaScript瀏覽器事件解析。這一篇主要寫一些經常使用的事件及一些可能的坑。node
表單事件
鍵盤事件
當 <input>
, <textarea>
的值發生變化時觸發。此外,打開 contenteditable 屬性的元素,只要值發生變化,也會觸發 input 事件。input 事件的一個特色,就是會連續觸發,好比用戶每次按下一次按鍵,就會觸發一次input事件。canvas
此類事件包括: keydown, keyup,segmentfault
鼠標事件
select 事件當在<input>
, <textarea>
中選中文本時觸發數組
change 事件當<input>
, <select>
, <textarea>
的值發生變化時觸發。它與 input 事件的最大不一樣,就是不會連續觸發,只有當所有修改完成時纔會觸發,並且input事件必然會引起change事件。具體來講,分紅如下幾種狀況:瀏覽器
- 激活單選框(radio)或複選框(checkbox)時觸發。
- 用戶提交時觸發。好比,從下列列表(select)完成選擇,在日期或文件輸入框完成選擇。
- 當文本框或textarea元素的值發生改變,而且喪失焦點時觸發。
- reset事件當表單重置(全部表單成員變回默認值)時由form元素觸發。
- submit事件當表單數據向服務器提交時由form元素觸發。
文檔事件:
beforeunload
beforeunload 事件當窗口將要關閉,或者 document 和網頁資源將要卸載時觸發。它能夠用來防止用戶不小心關閉網頁。該事件的默認動做就是關閉當前窗口或文檔。若是在監聽函數中,調用了 event.preventDefault(),或者對事件對象的 returnValue 屬性賦予一個非空的值,就會自動跳出一個確認框,讓用戶確認是否關閉網頁。若是用戶點擊「取消」按鈕,網頁就不會關閉。監聽函數所返回的字符串,會顯示在確認對話框之中:緩存
window.addEventListener('beforeunload', function(event) {
if(event.preventDefault){
event.preventDefault();
} else {
event.returnValue = '你確認要離開嗎?';
}
});
unload 與 load
unload 事件在窗口關閉或者 document 對象將要卸載時觸發,發生在 window, body, frameset 等對象上面。它的觸發順序排在 beforeunload, pagehide 事件後面。unload 事件只在頁面沒有被瀏覽器緩存時纔會觸發,換言之,若是經過按下「前進/後退」致使頁面卸載,並不會觸發 unload 事件。當 unload 事件發生時,document 對象處於一個特殊狀態。全部資源依然存在,可是對用戶來講都不可見,UI互動(window.open, alert, confirm方法等)所有無效。這時即便拋出錯誤,也不能中止文檔的卸載。服務器
load事件在頁面加載成功時觸發,error事件在頁面加載失敗時觸發。注意,頁面從瀏覽器緩存加載,並不會觸發load事件。session
這兩個事件實際上屬於進度事件,不只發生在 document 對象,還發生在各類外部資源上面。瀏覽網頁就是一個加載各類資源的過程,圖像(image), 樣式表(style sheet), 腳本(script), 視頻(video), 音頻(audio), Ajax請求(XMLHttpRequest)等等。這些資源和document對象, window對象, XMLHttpRequestUpload對象,都會觸發 load 事件和 error 事件。ide
pageshow 與 pagehide
pageshow事件,pagehide事件: 默認狀況下,瀏覽器會在當前會話(session)緩存頁面,當用戶點擊「前進/後退」按鈕時,瀏覽器就會從緩存中加載頁面。
pageshow 事件在頁面加載時觸發,包括第一次加載和從緩存加載兩種狀況。若是要指定頁面每次加載(無論是否是從瀏覽器緩存)時都運行的代碼,能夠放在這個事件的監聽函數。第一次加載時,它的觸發順序排在load事件後面。從緩存加載時,load 事件不會觸發,由於網頁在緩存中的樣子一般是 load 事件的監聽函數運行後的樣子,因此沒必要重複執行。同理,若是是從緩存中加載頁面,網頁內初始化的 JavaScript 腳本(好比 DOMContentLoaded 事件的監聽函數)也不會執行。pageshow 事件有一個 persisted 屬性,返回一個布爾值。頁面第一次加載時,這個屬性是false;當頁面從緩存加載時,這個屬性是true。函數
document.onpageshow = function(event){}
if(event.persisted){
//若是存緩存加載
}
}
一樣的,將這個屬性設爲 true,就表示頁面要保存在緩存中;設爲 false ,表示網頁不保存在緩存中,這時若是設置了 unload 事件的監聽函數,該函數將在 pagehide 事件後當即運行。若是頁面包含 frame ,則 frame 頁面的 pageshow 事件和 pagehide 事件,都會在主頁面以前觸發。
DOMContentLoaded 和 readystatechange
DOMContentLoaded 事件當 HTML 文檔下載並解析完成之後,就會在 document 對象上觸發 DOMContentLoaded 事件。這時,僅僅完成了 HTML 文檔的解析(整張頁面的DOM生成),全部外部資源(樣式表, 腳本, iframe等等)可能尚未下載結束。也就是說,這個事件比 load 事件,發生時間早得多。注意,網頁的 JavaScript 腳本是同步執行的,因此定義 DOMContentLoaded 事件的監聽函數,應該放在全部腳本的最前面。不然腳本一旦發生堵塞,將推遲觸發 DOMContentLoaded 事件。此外,IE8 不支持 DOMContentLoaded 事件,可使用 readystatechange 事件代替。
readystatechange 事件發生在 Document 對象和 XMLHttpRequest 對象,當它的 readyState 屬性發生變化時觸發。
其餘文檔級事件
上面重點提到了 DOMContentLoaded, readystatechange, pageshow, pagehide, unload, load 和 beforeunload 事件,此外還有一下事件:
- onafterprint: 文檔打印以後運行的腳本
- onbeforeprint: 文檔打印以前運行的腳本
- onbeforeunload: 文檔卸載以前運行的腳本(上文已涉及)
- onerror: 在錯誤發生時運行的腳本
- onhaschange: 當文檔已改變時運行的腳本
- onload: 頁面結束加載以後觸發(上文已涉及)
- onmessage: 在消息被觸發時運行的腳本
- onoffline: 當文檔離線時運行的腳本
- ononline: 當文檔上線時運行的腳本
- onpagehide: 當窗口隱藏時運行的腳本(上文已涉及)
- onpageshow: 當窗口成爲可見時運行的腳本(上文已涉及)
- onpopstate: 當窗口歷史記錄改變時運行的腳本
- onredo: 當文檔執行撤銷(redo)時運行的腳本
- onresize: 當瀏覽器窗口被調整大小時觸發
- onstorage: 在 Web Storage 區域更新後運行的腳本
- onundo: 在文檔執行 undo 時運行的腳本
- onscroll: 事件在文檔或文檔元素滾動時執行腳本
鼠標事件 與 MouseEvent對象
new MouseEvent(typeArg, mouseEventInit);
內置的鼠標事件包括:
- mousedown: 按下鼠標
- mouseup: 鼠標擡起
- click: 點擊
- dblclick: 雙擊
- mousemove: 鼠標移動
- mouseover: 鼠標移入,冒泡
- mouseout: 鼠標移出,冒泡
- mouseenter: 鼠標移入,不冒泡
- mouseleave: 鼠標移出,不冒泡
- contextmenu: 右鍵菜單
- wheel: 滾輪事件
其具備以下經常使用屬性:
- altKey,ctrlKey,metaKey,shiftKey屬性返回一個布爾值,表示鼠標事件發生時,是否按下某個鍵;
- button 返回事件的鼠標鍵信息, 值爲0(左鍵), 1或4(中鍵, 4爲IE中的值),2(右鍵),可經過switch來選擇執行分之);
- buttons 屬性返回一個3個比特位的值,表示同時按下了哪些鍵
- clientX,clientY 返回鼠標位置相對於瀏覽器窗口左上角的座標,單位爲像素
- screenX,screenY 返回鼠標位置相對於屏幕左上角的座標,單位爲像素
- movementX,movementY 返回一個位移,單位爲像素,表示當前位置與上一個 mousemove 事件之間的距離,在數值上:
currentEvent.movementX = currentEvent.screenX - previousEvent.screenX
currentEvent.movementY = currentEvent.screenY - previousEvent.screenY
- relatedTarget屬性返回事件的次要相關節點,即和target屬性對應的節點,如: mouseout target 指將要離開的節點,relatedTarget 指將要進入的節點。對於那些沒有次要相關節點的事件,該屬性返回null
- wheel 事件是與鼠標滾輪相關的事件,瀏覽器提供一個 WheelEvent 構造函數 new WheelEvent(typeArg, mouseEventInit)
- deltaX: 返回一個數值,表示滾輪的水平滾動量
- deltaY: 返回一個數值,表示滾輪的垂直滾動量
- deltaZ: 返回一個數值,表示滾輪的Z軸滾動量
- deltaMode: 返回一個數值,表示滾動的單位,適用於上面三個屬性。0表示像素,1表示行,2表示頁
鍵盤事件 KeyboardEvent 對象
構造函數 new KeyboardEvent(typeArg, KeyboardEventInit)
鍵盤事件包括keydown(按下鍵盤時觸發該事件),keypress(只要按下的鍵並不是Ctrl, Alt, Shift和Meta,就接着觸發keypress事件), keyup(鬆開鍵盤時觸發該事件)
- altKey,ctrlKey,metaKey,shiftKey: 返回一個布爾值,表示是否按下對應的鍵
- key: 返回一個字符串,表示按下的鍵名。若是同時按下一個控制鍵和一個符號鍵,則返回符號鍵的鍵名
- keyCode: 返回按鍵的 ASCII 碼,注意: 這裏是不區分大小寫的,
A鍵
不論輸出 A 仍是 a keyCode 都是68。在 IE 中使用 witch 屬性
進度事件 ProgressEvent對象
new ProgressEvent(type, {
lengthComputable: aBooleanValue, // false as default
loaded: aNumber, // 0 as default
total: aNumber // 0 as default
});
進度事件用來描述一個事件進展的過程,好比XMLHttpRequest對象發出的HTTP請求的過程, <img>
, <audio>
, <video>
, <style>
, <link>
加載外部資源的過程,包括下載和上傳。一般包括如下事件:
- abort事件: 當進度事件被停止時觸發。若是發生錯誤,致使進程停止,不會觸發該事件。
- error事件: 因爲錯誤致使資源沒法加載時觸發,不會冒泡。error 事件的監聽函數最好放在如 img 元素的 HTML 屬性中。
- load事件: 進度成功結束時觸發。
- loadstart事件: 進度開始時觸發。
- loadend事件: 進度中止時觸發,發生順序排在error事件abort事件load事件後面。loadend事件的監聽函數能夠用來取代abort事件/load事件/error事件的監聽函數,loadend事件自己不提供關於進度結束的緣由,但能夠用它來作全部進度結束場景都須要作的一些操做。
- progress事件: 當操做處於進度之中,由傳輸的數據塊不斷觸發。
- timeout事件: 進度超過限時觸發
這類事件具備如下屬性:
- lengthComputable: 返回一個布爾值,表示當前進度是否具備可計算的長度。若是爲false,就表示當前進度沒法測量。
- total: 返回一個數值,表示當前進度的總長度。若是是經過 HTTP 下載某個資源,表示內容自己的長度,不含 HTTP 頭部的長度。若是 lengthComputable 屬性爲 false,則 total 屬性就沒法取得正確的值。
- loaded: 返回一個數值,表示當前進度已經完成的數量。該屬性除以total屬性,就能夠獲得目前進度的百分比。
//進度計算
if (e.lengthComputable){
var percentComplete = e.loaded / e.total;
}
拖拽事件 DragEvent 對象
new DragEvent(type, DragEventInit);
拖拽指的是,用戶在某個對象上按下鼠標鍵不放,拖動它到另外一個位置,而後釋放鼠標鍵,將該對象放在那裏。拖拽的對象有好幾種,包括 Element 節點, 圖片, 連接, 選中的文字等等。在 HTML 網頁中,除了 Element 節點默認不能夠拖拽,其餘(圖片, 連接, 選中的文字)都是能夠直接拖拽的。爲了讓 Element 節點可拖拽,能夠將該節點的 draggable 屬性設爲 true。draggable 屬性可用於任何 Element 節點,可是圖片(img 元素)和連接(a 元素)不加這個屬性,就能夠拖拽。對於它們,用到這個屬性的時候,每每是將其設爲 false,防止拖拽。注意,一旦某個 Element 節點的 draggable 屬性設爲 true,就沒法再用鼠標選中該節點內部的文字或子節點了。
當Element節點或選中的文本被拖拽時,就會持續觸發拖拽事件,包括如下一些事件:
- drag事件: 拖拽過程當中,在被拖拽的節點上持續觸發。
- dragstart事件: 拖拽開始時在被拖拽的節點上觸發,該事件的target屬性是被拖拽的節點。一般應該在這個事件的監聽函數中,指定拖拽的數據。
- dragend事件: 拖拽結束時(釋放鼠標鍵或按下escape鍵)在被拖拽的節點上觸發,該事件的target屬性是被拖拽的節點。它與dragStart事件,在同一個節點上觸發。無論拖拽是否跨窗口,或者中途被取消,dragend事件老是會觸發的。
- dragenter事件: 拖拽進入當前節點時,在當前節點上觸發,該事件的target屬性是當前節點。一般應該在這個事件的監聽函數中,指定是否容許在當前節點放下(drop)拖拽的數據。若是當前節點沒有該事件的監聽函數,或者監聽函數不執行任何操做,就意味着不容許在當前節點放下數據。在視覺上顯示拖拽進入當前節點,也是在這個事件的監聽函數中設置。
- dragover事件: 拖拽到當前節點上方時,在當前節點上持續觸發,該事件的target屬性是當前節點。該事件與dragenter事件基本相似,默認會重置當前的拖拽事件的效果(DataTransfer對象的dropEffect屬性)爲none,即不容許放下被拖拽的節點,因此若是容許在當前節點drop數據,一般會使用preventDefault方法,取消重置拖拽效果爲none。
- dragleave事件: 拖拽離開當前節點範圍時,在當前節點上觸發,該事件的target屬性是當前節點。在視覺上顯示拖拽離開當前節點,就在這個事件的監聽函數中設置。
- drop事件: 被拖拽的節點或選中的文本,釋放到目標節點時,在目標節點上觸發。注意,若是當前節點不容許drop,即便在該節點上方鬆開鼠標鍵,也不會觸發該事件。若是用戶按下Escape鍵,取消這個操做,也不會觸發該事件。該事件的監聽函數負責取出拖拽數據,並進行相關處理。
關於拖拽事件,有如下幾點注意事項:
- 拖拽過程只觸發以上這些拖拽事件,儘管鼠標在移動,可是鼠標事件不會觸發。
- 將文件從操做系統拖拽進瀏覽器,不會觸發 dragStart 和 dragend 事件。
- dragenter 和 dragover 事件的監聽函數,用來指定能夠放下(drop)拖拽的數據。因爲網頁的大部分區域不適合做爲 drop 的目標節點,因此這兩個事件的默認設置爲當前節點不容許 drop。若是想要在目標節點上 drop 拖拽的數據,首先必須阻止這兩個事件的默認行爲,或者取消這兩個事件。
<div ondragover="return false">
//或
<div ondragover="event.preventDefault()">
- 拖拽事件用一個 DragEvent 對象表示,該對象繼承 MouseEvent 對象,DragEvent 對象只有一個獨有的屬性 dataTransfer,其餘都是繼承的屬性。dataTransfer 屬性用來讀寫拖拽事件中傳輸的數據,全部的拖拽事件都有一個 dataTransfer 屬性,用來保存須要傳遞的數據,這個屬性的值是一個 DataTransfer 對象。拖拽的數據保存兩方面的數據: 數據的種類(又稱格式)和數據的值。數據的種類是一個MIME字符串,好比 text/plain 或者 image/jpg,數據的值是一個字符串;
dataTransfer 對象的屬性的值是一個對象,其中包括如下屬性:
- dropEffect 屬性: 設置放下(drop)被拖拽節點時的效果,可能的值包括 copy(複製被拖拽的節點), move(移動被拖拽的節點), link(建立指向被拖拽的節點的連接), none(沒法放下被拖拽的節點)。設置除此之外的值,都是無效的。
- effectAllowed 屬性: 設置本次拖拽中容許的效果,可能的值包括 copy, move, link, copyLink, copyMove, linkMove, all, none, uninitialized(默認值,等同於 all)。若是某種效果是不容許的,用戶就沒法在目標節點中達成這種效果。
- files 屬性: 是一個 FileList 對象,包含一組本地文件,能夠用來在拖拽操做中傳送。若是本次拖拽不涉及文件,則屬性爲空的 FileList 對象。經過files屬性讀取拖拽文件的信息。若是想要讀取文件內容,就要使用 FileReader 對象。
- types 屬性: 是一個數組,保存每一次拖拽的數據格式,如'text/uri-list'
- setData() 方法: 用來設置事件所帶有的指定類型的數據。它接受兩個參數,第一個是數據類型,第二個是具體數據。若是指定的類型在現有數據中不存在,則該類型將寫入types屬性;若是已經存在,在該類型的現有數據將被替換。
event.dataTransfer.setData("text/plain", "Text to drag");
- getData() 方法接受一個字符串(表示數據類型)做爲參數,返回事件所帶的指定類型的數據(一般是用 setData 方法添加的數據)。若是指定類型的數據不存在,則返回空字符串。
event.dataTransfer.getData(types[0]);
- clearData() 方法接受一個字符串(表示數據類型)做爲參數,刪除事件所帶的指定類型的數據。若是沒有指定類型,則刪除全部數據。若是指定類型不存在,則原數據不受影響。
event.dataTransfer.clearData("text/uri-list");
- setDragImage() 能夠用來自定義這張圖片,它接受三個參數,第一個是img圖片元素或者canvas元素,若是省略或爲null則使用被拖動的節點的外觀,第二個和第三個參數爲鼠標相對於該圖片左上角的橫座標和右座標。
event.dataTransfer.setDragImage(img, 0, 0);
觸摸事件
new Touch(touchInit);
觸摸事件包括如下5種:
- touchstart: 用戶接觸觸摸屏時觸發,它的 target 屬性返回發生觸摸的 Element 節點(IE10+中使用 mspointerdown 事件);
- touchend: 用戶再也不接觸觸摸屏時(或者移出屏幕邊緣時)觸發,它的 target 屬性與 touchstart 事件的 target 屬性是一致的,它的 changedTouches 屬性返回一個TouchList對象,包含全部再也不觸摸的觸摸點(Touch對象)(IE10+中使用 mspointerup 事件);
- touchmove: 用戶移動觸摸點時觸發,它的 target 屬性與 touchstart 事件的 target 屬性一致。若是觸摸的半徑, 角度, 力度發生變化,也會觸發該事件。(IE10+中使用 mspointermove 事件);
- touchenter: 當觸點進入某個 element 時觸發。此事件沒有冒泡過程。(IE10+中使用 mspointerover 事件);
- touchleave: 當觸點離開某個 element 時觸發。此事件沒有冒泡過程。(IE10+中使用 mspointerout 事件);
- touchcancel: 當觸點因爲某些緣由被中斷時觸發。有幾種可能的緣由以下(具體的緣由根據不一樣的設備和瀏覽器有所不一樣):(IE10+中沒有對應事件);
-
- 因爲某個事件取消了觸摸: 例如觸摸過程被一個模態的彈出框或電話打斷;
-
- 觸點離開了文檔窗口,而進入了瀏覽器的界面元素, 插件或者其餘外部內容區域;
-
- 當用戶產生的觸點個數超過了設備支持的個數,從而致使 TouchList 中最先的 Touch 對象被取消。
觸摸 API 由三個對象組成。每一個 Touch 對象表明一個觸點; 每一個觸點都由其位置,大小,形狀,壓力大小,和目標 element 描述。 TouchList 對象表明多個觸點的一個列表。具體包括如下屬性:
- identifier 屬性: 表示touch實例的獨一無二的識別符。它在整個觸摸過程當中保持不變(IE10+中使用 pointerId 屬性);
- screenX/screenY 屬性: 分別表示觸摸點相對於屏幕左上角的橫座標和縱座標,與頁面是否滾動無關;
- clientX/clientY 屬性: 分別表示觸摸點相對於瀏覽器視口左上角的橫座標和縱座標,與頁面是否滾動無關;
- pageX/pageY 屬性: 分別表示觸摸點相對於當前頁面左上角的橫座標和縱座標,包含了頁面滾動帶來的位移;
- radiusX/radiusY 屬性: 分別返回觸摸點周圍受到影響的橢圓範圍的X軸和Y軸,單位爲像素;
- rotationAngle 屬性: 表示觸摸區域的橢圓的旋轉角度,單位爲度數,在0到90度之間。指尖接觸屏幕,觸摸範圍會造成一個橢圓,這三個屬性就用來描述這個橢圓區域(IE10+中使用 rotation 屬性);
- force 屬性: 返回一個0到1之間的數值,表示觸摸壓力。0表明沒有壓力,1表明硬件所能識別的最大壓力(IE10+中使用 pressure 屬性,取值0 - 255);
- target 屬性: 返回一個Element節點,表明觸摸發生的那個節點。當這個觸點最開始被跟蹤時(在 touchstart 事件中), 觸點位於的HTML元素.哪怕在觸點移動過程當中, 觸點的位置已經離開了這個元素的有效交互區域, 或者這個元素已經被從文檔中移除. 須要注意的是, 若是這個元素在觸摸過程當中被移除, 這個事件仍然會指向它, 可是不會再冒泡這個事件到 window 或 document 對象. 所以, 若是有元素在觸摸過程當中可能被移除, 最佳實踐是將觸摸事件的監聽器綁定到這個元素自己, 防止元素被移除後, 沒法再從它的上一級元素上偵測到從該元素冒泡的事件. 只讀屬性.
- altKey/ctrlKey/metaKey/shiftKey 都爲只讀屬性: 返回一個布爾值,表示觸摸的同時,是否按下某個鍵
- changedTouches 屬性: 返回一個 TouchList 對象,包含了由當前觸摸事件引起的全部Touch對象(即相關的觸摸點)。它包含了表明全部從上一次觸摸事件到這次事件過程當中,狀態發生了改變的觸點的 Touch 對象。只讀屬性。
- targetTouches屬性: 返回一個 TouchList 對象,包含了觸摸的目標 Element 節點內部,全部仍然處於活動狀態的觸摸點。
- touches 屬性返回一個 TouchList 對象(類數組的對象),包含了全部當前接觸觸摸平面的觸點的 Touch 對象,不管它們的起始於哪一個 element 上,也不管它們狀態是否發生了變化。只讀屬性
- type 屬性: 指這次觸摸事件的類型。
- target屬性: 這次觸摸事件的目標 element 。這個目標元素對應 TouchEvent.changedTouches 中的觸點的起始元素(在以後的事件類型中有說明),可是請注意: 這次事件中其餘的觸點的起始元素可能有所不一樣。以防萬一,應使用和每個單獨觸點相關聯的目標 。
如下是 IE10+ 中的其餘屬性:
- hwTimestamp: 建立事件時間(毫秒);
- isPrimary: 表示該時間是不是主事件;
- pointerType: 取值自 event.MSPOINTER_TYPE_TOUCH, event.MAPOINTER_TYPE_PEN, event.MSPOINTER_TYPE_MOUSE, 表示觸摸設備;
- tilt[X|Y]: 筆的傾斜程度;
舉一個簡單例子:
function handleMove(evt) {
evt.preventDefault(); // 阻止瀏覽器繼續處理觸摸事件,也阻止發出鼠標事件
var touches = evt.changedTouches;
for (var i = 0; i < touches.length; i++) {
var id = touches[i].identifier;
var touch = touches.identifiedTouch(id);
console.log(touch.pageX, touch.pageY);
}
}
對於跨平臺交互,我封裝了一個 tap相關事件以下:
//如下代碼並未兼容低版本 IE
function addTapListener(node, callback){
var startEvent = window.onmousedown ? window.onmspointerdown ? 'mspointerdow' : 'mousedown' : 'touchstart';
var event = window.onclick ? 'click' : 'touch';
var endEvent = window.onmouseup ? 'mouseup' : 'touchend';
node.addEventListener(startEvent, function(e){
var tap = document.createEvent('CustomEvent');
tap.initCustomEvent('tapstart', true, true, null);
node.dispatchEvent(tap);
});
node.addEventListener(event, function(e){
var tap = document.createEvent('CustomEvent');
tap.initCustomEvent('tap', true, true, null);
node.dispatchEvent(tap);
});
node.addEventListener(endEvent, function(e){
var tap = document.createEvent('CustomEvent');
tap.initCustomEvent('tapend', true, true, null);
node.dispatchEvent(tap);
});
node.addEventListener('tap', callback);
}
固然本文僅僅列舉了一些經常使用事件,其實事件還有不少,本文會在必要的時候繼續更新,但即使如此也不可能窮盡全部的事件,好比還有動畫事件: animationstart, animation, animationend 等等。