Javascript中的事件物件和事件型別
阿新 • • 發佈:2021-02-24
#### *接上次看JS的事件冒泡和捕獲,所以順帶就把`事件`相關的知識都看完好了*
#### *而且想到一個好的學習方法,第一天自己看,第二天把前一天學習的東西寫下來,一方面可以當複習,一方面當重新整理並且分享*
----
## 事件物件
事件處理程式函式在處理事件時,或者說`DOM`在觸發某個事件的時候,會產生一個包含事件相關資訊的`event`事件物件
對於不同瀏覽器環境,這個`event`事件物件有一些差距
* ### DOM中的事件物件
*不管是`DOM0`級還是`DOM2`級*
相容`DOM`的瀏覽器會將一個`event`物件傳入事件處理程式中
常用的`event`物件的一些屬性
* `type`:表示事件的型別
具體用法:可以通過`type`區分,在同一個事件處理函式實現多個事件的處理,減少事件監聽,優化效能
* `currentTarget`:事件處理程式當前正在處理這個事件的元素
* `target`: 表示實際觸發事件的DOM元素,實際目標
可以這麼理解,`body`下面的`div`被點選,冒泡到`body`,在`body`上綁定了一個`click`事件,這個時候觸發這個`body`的點選事件,但是這個時候的`target`實際上是`div`
那麼在事件處理程式中,還有一個`this`屬性,還有一個`currentTarget`:永遠指向正在處理這個事件的元素,那麼上一個例子中實際上是`body`在處理這個事件,所以`currentTarget`是指向`body`的
而 事件處理程式中的`this`指向,是一直指向`currentTarget`表示正在執行和處理事件的這個元素
所以,在事件沒有冒泡的情況下,這三者是可以為同一個值,但是如果是在冒泡階段事件被處理的話,則這個`target`可能不等於其他兩個值
* `preventDefault` 阻止預設行為,是一個函式
用法:在需要阻止預設行為的事件處理函式中,使用`event.preventDefault()`,取消預設事件,比如預設點選`a`標籤會跳轉指定連結等等
注意: 只有`event.cancleable`屬性為`true`的事件型別,才可以使用`preventDefault`
* `stopPropagation` 阻止事件**冒泡和捕獲**,也是一個函式
* 這個用的比較常見,阻止事件冒泡和捕獲,只要這個事件被處理,不會順著事件流往*捕獲方向或者冒泡方向*傳遞
* `eventPhase` 獲取事件當前正處於事件流的哪個階段
* 事件流三個階段: **捕獲階段,冒泡階段,處於目標階段**
* 事件處理程式中的`event.eventPhase`分別對應值:**1,3,2**
* **上述`event`屬性和方法,盡在事件處理程式執行期間存在,事件處理程式一旦執行完畢,會立即銷燬**
* ### IE中的事件物件
**IE中的`event`物件跟`DOM`中的事件物件有一定的差別,最重要的就是`IE`中的事件物件,如果是使用`DOM0`級的方法新增事件處理程式是,`event`物件會掛載到`window`下面?window?window?是的沒錯,獲取事件物件的時候,是通過`window.event`來拿到事件物件,如果使用`html`指定事件處理程式或者是`DOM2`級都都不會有這個問題,和`DOM`級別類似,會有一個`event`物件傳入到事件處理程式**
**但是`IE`中的事件物件,對應的屬性名和方法名跟`DOM`中事件物件的名字有很大不一樣**
* `cancelBubble == stopPropagation `**阻止事件冒泡,但是不是個方法是一個屬性**
* `returnValue == preventDefault` **阻止預設事件,但是不是個方法,是一個屬性**
* `srcElement == target`實際觸發目標
* `type == type`用來區分事件型別,這個沒有區別
**要記住的還是,如果在`IE`環境下,使用`DOM0`級指定事件處理程式的話,獲取`event`物件需要從`window.event`這樣獲取**
例如:
```js
var btn= document.getElementById('test')
// DOM0級指定
btn.onclick=function(){
alert(window.event.target.srcElement === this) //true
}
// DOM2級
btn.addEventListener('click',function(event){
alert(event.srcElment === this) //true
})
```
**還有就是`IE`環境下阻止事件冒泡和預設處理程式都是屬性,不是方法,只需要把對應的屬性設定為`false`**
例如:
```js
var link = document..getElementById('test')
link.onclick = function(){
window.event.returnValue = false; //阻止預設事件
}
```
**`IE`中的cancleBuble只是取消冒泡,因為IE環境不支援事件捕獲,哈哈哈哈**
**然後就是完善一下之前的`EventUtil`,實現跨瀏覽器的獲取事件物件,還有阻止冒泡和預設事件處理程式,程式碼如下**
```js
getTarget(event){
return event || window.event //IE環境下可能是WINDOW.event
},
preventDefault(event){
if(event.preventDefault){
event.preventDefault()
}else{
event.returnValue = false // IE環境下沒有preventDefault,是通過設定returnValue取消預設
}
},
stopPropagation(event){
if(event.stopPropagation){
event.stopPropagation()
}else{
event.cancelBuble = false
}
}
```
## 事件型別
*DOM3級完善了事件型別,用來區分事件型別的不同資訊,類似:滑鼠事件,焦點事件,鍵盤事件,文字時間,滾輪事件等等*
* ### UI事件
*指的是那些不一定與使用者操作有管的事件,包括一些DOM和元素的互動時間,例如`load`事件 `unload`事件*
* `load`事件
* 最常用的事件,
* 觸發物件: `window`,
* 觸發時間:頁面完全載入後(包括所有影象,JS檔案,CSS等外部資源)
* 如何捕獲:
* `DOM2`級寫法:監聽`window`物件,例如`window.addEventListener('load',function(){})`
* `HTML`級寫法,由於`HTML`寫法無法拿到`window`物件,所以會直接寫在`body`上面,**一般來說,在`window`上發生的任何事件都可以在`body`元素上通過對應的特性來指定,所有的瀏覽器都能很好地支援這種方式,但是任然推薦使用`DOM0`或`DOM2`等`javascript`的方法來繫結`window`物件的時間按處理程式**
* `img,script,link,video`等標籤也有`load`事件
* `unload`事件
* 一般用來:在這個事件**清除引用,清理記憶體**
* 觸發物件:`window`
* 觸發時間:文件被完全解除安裝之後觸發,**此時可能一些物件和變數已經被解除安裝,注意引用關係**
* `resize`事件
* **區別:在`DOM`瀏覽器和`IE`環境有區別,`event.target`屬性的實際觸發物件不一樣,在`DOM`瀏覽器中,這個屬性指向`document`,但是在`IE`環境中,這個值沒有指定**
* **相容性:在`firefox`瀏覽器,`resize`的過程不會持續觸發這個事件,只在開始和結束,兩個觸發,而在其他瀏覽器,在拖拽的過程中是會一直觸發這個事件**
* 觸發物件:`window`
* 觸發事件:視窗大小發生`1px`的改變時候,最大最小化視窗的時候
* 如何捕獲:參考`load`事件,可以用`window`物件捕獲,也可以用`body`標籤捕獲
* `scroll`事件
* 觸發物件:`window`
* 捕獲方式: 和`load`方法類似
* **注意:根據`document.compatMode`渲染模式,有不同的表現,在`compatMode==='CSS1Copat'`標準模式時,除了`Safari`瀏覽器,所有的都會通過`html`這個元素反應這個變化,而在混雜模式時,是通過`body`元素的`scrollLeft`和`scrollTop`來獲取這個具體的bian'hua數值,而現在基本上混雜模式和標準模式已經混合了,區分沒有這麼詳細**
* ### 焦點事件
*在頁面元素失去或者獲得焦點的時候觸發,可以用來知曉使用者在頁面上的行蹤*
主要用的比較多的是
`focus`,`blur`,這兩個事件表示,元素獲得焦點和失去焦點,**不會冒泡**
`focusin,focusout`用來表示焦點進入和焦點失去事件,**這兩個事件會冒泡
**雖然上述常用事件有的不會冒泡什麼,但是,仍然會走捕獲階段,所以仍然可以通過捕獲階段進行一些外級操作,當然是瀏覽器支援捕獲階段**
觸發元素:**所有元素都可觸發**
捕獲方式:`DOM0`級,`DOM2`級,或者`HTML`方法均可捕獲,`IE`瀏覽器環境方式也可以
* ### 滑鼠與滾輪事件
*滑鼠和滾輪事件也是在`DOM3`級事件中定義的,主要有,單擊,點選,雙擊,滑鼠移入,滑鼠移出,等*
**除了滑鼠移入`mouseenter`和滑鼠移除`mouseleave`所有的滑鼠事件都會冒泡,也是可以取消的,而取消滑鼠事件將會影響瀏覽器的預設行為,取消滑鼠事件的預設行為還會影響其他事件,因為滑鼠事件可能和其他事件是有聯絡的**
**一個`click`事件,前面包括了一個滑鼠按下`mousedown`和滑鼠放開兩個事件`mouseup`,也就是觸發`click`事件前會先觸發前兩個事件**
**同理,雙擊事件`doubleclick`事件包括兩個`click`事件,前面又有兩個`mouseup`和`mousedown`事件**
**主要用處**
* 客戶區座標位置
* `event.clientX`和`event.clientY`
* 滑鼠事件,相對於**瀏覽器視口**的位置
* 頁面座標位置
* `event.pageX`和`event.pageY`
* 滑鼠事件,相對於**頁面**的位置
* **IE8及更早版本不支援這兩個屬性,但是也可以通過滑鼠相對於視口位置+頁面滾動屬性算出=滑鼠相對於頁面的位置**
* 螢幕座標位置
* `event.screenX`和`event.screenY`
* 滑鼠事件,相對於**整個螢幕**的位置
* 修改鍵/點選滑鼠時同時按下了多功能鍵(`ctrl`,`alt`等)
* 對應的鍵,直接在點選事件的對應屬性上面
* 例如:`shift`鍵 就在 `event.shiftKey`這個屬性上
* 相關元素
* **滑鼠移入移出的來源元素和目標元素**
* 獲取方式: `event.relatedTarget`
* 分別在`mouseout`和`mouseenter`時表示 **目標獲取游標元素和目標失去游標元素**
* 在`IE8`之前的沒有這個屬性,但是分別有兩個`fromElment`和`toElement`用來獲取這兩個相關元素
* 滑鼠按鈕
* 滑鼠事件(例如點選事件時,點選的是哪個按鈕,左鍵,中鍵,右鍵等)
* 屬性名:`button`
* 屬性含義:`0 : 左鍵按下,1:中鍵按下,2:右鍵按下`
* `IE8`及更早版本瀏覽器也有這個屬性,但是對應值有比較大的區別,區分的更為細緻
* 更多事件資訊
* 屬性名: `detail`
* 表示滑鼠點選次數
* 滑鼠滾輪事件
* 我真是沒想到支援的這麼詳細,hhh
* 觸控裝置
* 這個還和後面的觸控事件有一定的區別
* 這個表示滑鼠事件在一些移動裝置中的區別表現
* 例如:
* 在移動裝置中不支援`dblclick`事件,雙擊會放大畫面,而且不能改變該行為
* 輕擊可點選單元會觸發`mousemove`事件,如果此事件會導致內容變化,將不再發生其他事件,如果不會觸發任何事件,那麼依次會發生`mousedown,mouseup,click`事件,可點選單元表示一些會產生預設操作的元素:比如`a`標籤
* 無障礙性問題
* 滑鼠裝置事件需要針對無障礙性考慮更多易用性和點選操作邏輯
* ### 鍵盤與文字事件
*主要是一些鍵盤輸入和文字鍵入的事件,是說`DOM2`級事件最初規定了鍵盤事件,但是後來刪掉了,所以目前主要支援的還是`DOM0級`事件和`DOM3`級事件,但是`DOM3`級事件暫時沒有特別完善*
主要事件`keydown`,`keypress`,`keyup`,理論上所有的元素都支援這三個事件,但是實際上只有文字輸入框支援最多
**觸發順序`keydown,keypress,keyup`,並且`keydown`和`keypress`都是在文字框發生變化之前觸發,而`keyup`事件則是在文字框已經變化之後觸發,如果使用者一直按住一個字元不放,則會一直觸發`keydown`和`keypress`事件**
**還有一個新增的文字事件`textInput`,實際上是對`keypress`的補充,用意是將文字顯示給使用者之前更加容易攔截文字,在文字插入文字框之前會觸發`textInput`事件**
常用鍵盤事件屬性
* **鍵碼`keyCode`**
* 觸發時間:`keydown`和`keyup`時,event物件會有一個`keyCode`屬性
* 表示:按下按鍵的對應的小寫字母或數字對應的ASCII碼相同
* **字元編碼`charCode`**
* 觸發時間:`keypress`事件觸發時
* 使用方式: 首先檢查`charCode`是否可用,如果有的話則表示的是 **按下鍵對應字元的ASCII碼**,而`IE8`及更早版本,則是在`keyCode`表示字元對應的ASCII碼
* 所以:**字元對應的ASCII碼不一定在`charCode`,在`IE8`及老舊瀏覽器也可能在`keyCode`**
* 用法:如果`charCode`可用的話,可以通過字串類方法`String.fromCharCode`轉化為實際的字元
* **DOM3級新增了 `char`和`key`**
* 同時整合了`charCode`和`keyCode`
* `key`:表示對應的文字字元,包括大小寫,就是實際的鍵入字元
* `char`:表現形式在按下字元時表現和`key`一致,但是對於非字元時,`char`為`null`
* 新增了`location`屬性,表示按下了鍵盤什麼位置的同一個按鍵,例如鍵盤左邊的`shift`和右邊的`shift`
* **textInput事件**
* 新增的文字輸入事件,只在可編輯區域觸發,主要用域監聽文字的變化,新增data屬性,表示修改實際文字
* 新增屬性: `inputMethod`,用來區分輸入方式,是複製進來的,還是拖放進來的,還是手寫輸入,語音輸入等
*
**DOM3級的鍵盤輸入事件很美好,但是不知道實際支援情況,而且還要做相容,之前遇到一個`number`型別的`input`輸入框,就累個夠嗆,候選字等,輸入法越做越優秀,事件越來越複雜**
* 裝置中的其他按鍵事件
* 例如一些手柄的事件,加號,減號等,暫時沒用到
* ### 複合事件
*是`DOM3`級新增的一類事件,用域處理`IME`的輸入序列,暫時沒接觸,也是一類多功能輸入事件吧*
* ### 變動事件
*是`DOM2`級的變動事件*
表示:DOM中某一部分發生變化時給出提示,變動事件是為`XML`或者`HTML DOM`設計的,並不特定於某種語言。
主要有:
* 節點移除
* 節點插入
* 刪除節點等
* ### HTML5事件
* `contextmenu`上下文選單事件
* 意義:通過滑鼠右鍵,調出上下文選單,滑鼠右鍵顯示事件
* 觸發元素:所有元素,
* 是否冒泡:會冒泡
* 注意:**首先需要阻止預設事件處理程式,然後重新寫事件處理程式,有可能影響瀏覽器預設行文**
* `beforeunload`事件
* 意義:頁面解除安裝之前用來挽留頁面
* 觸發元素: `window`物件
* `DOMContentLoaded`事件
* 意義:`DOM`樹完整形成之後觸發
* 觸發元素: `window`物件
* `readystatechange`事件
* 意義:元素載入狀態發生變化時
* 觸發元素:部分媒體元素,`script`標籤等
* 每個物件都有一個`readystate`的狀態屬性,會有以下狀態(但不是所有狀態都會正常變化)
* `uninitialized`未初始化狀態
* `loading`正在載入
* `loaded`載入完畢
* `interactive`可以操作物件
* `complete`完成
* 但是不是所有物件都有這些完整的階段,可能會跳過
* `pagehide`和`pageshow`事件
* 意義:從記憶體中取出/進入視野時觸發,不會觸發`load`事件,不會重新載入頁面,只是從頁面回顯
* 一般發生在:前進/後退按鈕點選的時候
* 相關屬性`event.persisted`是否被快取在`bfcache`中
* 觸發元素:`window`
。。。太多了,還有好多事件型別,回頭再填坑了,記錄不