DOM事件類型、event事件對象,最詳解析。

目錄

事件對象定義

在觸發DOM上的某個事件時,會產生一個事件對象event,這個事件對象包含着所有與事件有關的信息,例如事件是冒泡還是捕獲,事件的目標,鼠標座標,鍵盤按下的鍵,等等信息,不要太好用

下面一起來看看event事件對象都有哪些內容吧。

小提示:在頁面中按 Ctrl + F 可以查詢關鍵字,以便搜索到你想要的內容。

(一)DOM中的事件對象

兼容DOM的瀏覽器會將一個event對象傳入到事件處理程序中。無論DOM0級或者DOM2級方法,都會傳入event對象,例如:

(1) 示例

<body>
    <ul>
        <li data-index="0"></li>
        <li data-index="1"></li>
        <li data-index="2"></li>
        <li data-index="3"></li>
        <li data-index="4"></li>
    </ul>
    <script>
        var oUl = document.querySelector("ul");
        var aLi = document.querySelectorAll("ul>li");
        oUl.addEventListener("click",function(event){
            alert(event.target.getAttribute("data-index"))//彈出我自定義的索引值
        })
        aLi[0].onclick = function(e){
            alert(e.target.getAttribute("data-index"))//彈出我自定義的索引值
        }
    </script>
</body>

據上述代碼,有兩點需要提及一下

  • 瀏覽器確實會將event對象傳入到事件處理程序中,但對於形參設置成什麼,並沒有要求,只要保持形參和實參相統一就好了,一般會使用event或 e。要是不統一,一定要在函數體內部使用event。
  • 這裏我使用了事件委託,target表示事件的目標(也就是誰觸發了事件,是第一個li還是第二個li?),下面會解釋。

接下來看看效果:
在這裏插入圖片描述
可以看到,兩個事件都被觸發了,分別彈出了第一個li的索引值。

在這個示例中,event事件對象起到的作用就是利用了裏面的target屬性,來幫我找到了是誰觸發了Ul的點擊事件,然後彈出它的索引值。

通過這個示例,引出所有事件都會有的event對象的屬性和方法(後面我會解析包括鼠標,鍵盤在內的所有event的屬性和方法):

(2)所有事件都有的event對象的屬性和方法

屬性/方法 類型 讀/寫 說明
bubbles Boolean 只讀 表明事件是否冒泡
cancelable Boolean 只讀 表明是否可以取消時間的默認行爲
currentTarget Element 只讀 誰綁定的事件,currentTarget 就是誰,與this類似
defaultprevented Boolean 只讀 值爲true則表示已經調用了preventDefault( )
eventPhase Integer 只讀 調用事件處理程序的階段:1表示捕獲階段,2表示目標階段,3表示冒泡階段
preventDefault( ) Function 只讀 取消事件的默認行爲。如果cancelable爲true,則可以使用這個方法
stopImmediatePropagation( ) Function 只讀 取消事件的進一步捕獲或冒泡,同時阻止任何事件處理程序被調用
stopPropagation( ) Function 只讀 取消事件的進一步捕獲或冒泡
target Element 只讀 事件的目標,誰觸發了事件就是誰
isTrusted Boolean 只讀 爲true表示事件是瀏覽器生成的,false則表示事件是開發人員通過JavaScript創建的
type String 只讀 被觸發的事件的類型,例如click,mouseout,blur
view AbstractView 只讀 與事件關聯的抽象視圖。等同於發生事件的window對象

光是所有事件都有的屬性方法已經如此之多,頭頂發涼~~

下面着重分析一下較重要的點:

① currentTarget | this | targer 的區別

    <script>
        var oUl = document.querySelector("ul");
        var aLi = document.querySelectorAll("ul>li");
        oUl.addEventListener("click",function(e){
            console.log("this === "+this.tagName)
            console.log("e.currentTarget === "+e.currentTarget.tagName)
            console.log("e.target === "+e.target.tagName)
            console.log("e.target的索引值 === "+e.target.getAttribute("data-index"))
            console.log("=================================")
        })
    </script>

代碼說明: tagName只是爲了獲取標籤名,getAttribute只是爲了獲取li的索引值,可以更直觀的看出區別

在這裏插入圖片描述
可以明顯的看到,this和currentTarget始終相同,等於ul。而target始終爲li。
currentTarget :誰綁定了事件,我就指向誰
target : 誰觸發了事件,我就指向誰

② type的作用

type能夠返回事件的類型,因此,我們只需要定義一個函數,讓不同的事件綁定一個相同的函數
看看實例:

 <script>
        var oInput = document.querySelector("input")
        function show(e) {
            switch (e.type) {
                case "click":
                alert("你點擊了我");
                break;
                case "mouseover":
                alert("你移入了我");
                break;
                case "mouseout":
                alert("你移出了我");
                break;
            }
        }
        oInput.addEventListener("click",show)
        oInput.addEventListener("mouseover",show)
        oInput.addEventListener("mouseout",show)
    </script>

在這裏插入圖片描述

③ preventDefault( ) 取消默認行爲

例如,鏈接的默認行爲就是在單擊時會跳轉到指定的URL,如果想阻止這一默認行爲,請使用 preventDefault( )

    <script>
        var oA = document.querySelector("a");
        oA.addEventListener("click",function(e){
            e.preventDefault();
        })
    </script>

④ stopPropagation( ) 阻止事件進一步捕獲或冒泡

這個可能會有點繞,我們來細分一下,首先看看代碼

<script>
    var oSection = document.querySelector("section");
    var oDiv = document.querySelector("div");
    oDiv.addEventListener("click",function(e){
        alert("我是子盒子,我在捕獲階段")
    },true)
    oDiv.addEventListener("click",function(e){
        alert("我是子盒子,我在冒泡階段")
    })
    oSection.addEventListener("click",function(e){
        alert("我是父盒子,我在捕獲階段")
    },true)
    oSection.addEventListener("click", function (e) {
        alert("我是父盒子,我在冒泡階段")
    })
    oBody.addEventListener("click",function(e){
        alert("我是body,我在捕獲階段")
    },true)
    oBody.addEventListener("click", function (e) {
        alert("我是body,我在冒泡階段")
    })
</script>

代碼說明:div-section-body爲嵌套關係,div最小,若點擊div,則事件傳播流程如下圖

在這裏插入圖片描述

可以看到,從body捕獲到body冒泡,用箭頭鏈接起來了,把箭頭想象成一條線,將它們串起來。在何處使用e.stopPropagation(),就相當於在何處剪斷這根線(事件是從線的最左端端開始的)


(二)UI

事件類型 :

Ul事件指的是那些不一定與用戶操作有關的事件。

(1) 加載完成後

事件名:load

  • 當頁面完全加載後在window上面觸發
  • 當所有框架都加載完畢時在框架集上面觸發
  • 當圖像加載完畢時在img元素上面觸發
  • 當嵌入內容加載完畢時在Object元素上面觸發

示例,當圖片加載完畢時

<body>
<img src="./Img/time-1.png">
    <script>
        var oImage = document.querySelector("img");
        oImage.addEventListener("load",function(){
            alert("加載完畢")
        })
    </script>
</body>

(2) 卸載完成後

事件名:unload

用戶從一個頁面跳轉到另一個頁面時,就會發生unload事件。而利用這個事件最多的情況就是清除引用,避免內存泄漏。

具體參照load事件

(3) 用戶選取文本時

事件名:select

(4) 窗口或框架大小改變時

事件名:resize

(5) 用戶滾動文檔時

事件名:scroll

在混雜模式下,可以通過body元素的 scrollLeft 和 scrollTop 來監控這一變化
而在標準模式下,除Safari之外的所有瀏覽器都會通過html元素來監控這一變化。

(二)焦點

事件類型 :

(1) 失去焦點時(不會冒泡)

事件名:blur

(2) 獲取焦點時(不會冒泡)

事件名:focus

(3) 失去焦點時(冒泡)

事件名:focusout

(4) 獲取焦點時(冒泡)

事件名:focusin


(三)鼠標/滾輪

△ 事件類型 :

(1) 單擊

事件名:click

在用戶單擊主鼠標按鈕(一般是左邊的按鈕)或者按下鍵盤的回車鍵時觸發。這一點對確保易訪問性很重要,意味着onclick事件處理程序可以通過鼠標也可以通過鍵盤執行

(2) 雙擊

事件名:dblclick

在用戶雙擊主鼠標時觸發

(3) 按下任意鼠標按鈕時

事件名:mousedown

(4) 擡起任意鼠標按鈕時

事件名:mouseup

在用戶釋放鼠標按鈕時觸發,不能通過鍵盤觸發這個事件

click 和 dblclick 事件都會依賴於其他的先行事件;而mousdown 和 mouseup 不受影響,因爲一個click事件也觸發了mousdown 和 mouseup

不能通過鍵盤觸發這個事件

(5) 鼠標指針首次移入到元素範圍內時(不冒泡)

事件名:mouseenter

這個事件不但不冒泡,而且在光標移動到後代元素上不會觸發

(6) 鼠標指針移出元素時(不冒泡)

事件名:mouseleave

這個事件不但不冒泡,而且在光標移動到後代元素上不會觸發

(7) 鼠標指針在元素內移動

事件名:mousemove

重複觸發

(8) 鼠標指針移入元素

事件名:mouseover

在光標位於一個元素上,然後又移入另一個元素時觸發(這個元素可以是子元素),不能通過鍵盤觸發這個事件

(9) 鼠標指針移出元素

事件名:mouseout

同上!

(9) 滾輪事件

IE6首先實現了mousewheel事件。此後,Opera,Chrome 和 Safari也都實現了這個事件。但Firefox不同,它的類似事件是DOMMouseScroll,而且它有關鼠標滾輪的信息則保存在detail屬性中(下面會提到)

事件名:mousewheel

事件名:DOMMouseScroll(火狐)

無論向上向下滾動,都會觸發,最終會冒泡到 document 或 window對象

小提示:如果你想讓指定元素觸發滾動事件,而不想讓文檔滾動,可以取消默認事件


△ 事件對象

(1) 相對於瀏覽器窗口可視區域的鼠標座標

clientX,clientY

首先我設置了body的寬高均爲3000px

在這裏插入圖片描述
注意指針在滾動條內,和滾動條滾動時候的變化。

(2) 相對於文檔區域的鼠標座標

pageX,pageY
在這裏插入圖片描述

(3) 相對於電腦屏幕的鼠標座標

screenX,screenY

這個很好懂,就不演示了

(4) 修改鍵

雖然鼠標事件主要是使用鼠標來觸發的,但在按下鼠標時鍵盤上的某些鍵的狀態也可以影響到所要採取的操作。這些修改鍵就是Shift、Ctrl、Alt和Meta(在Windows鍵盤中是Windows鍵,在蘋果機中是Cmd鍵) ,它們通常被用來修改鼠標事件的行爲。
DOM爲此規定了4個屬性,表示這些修改鍵的狀態:shiftKey,ctrlKey,altKey和metaKey。這些屬性中包含的都是布爾值,如果相應的鍵被按下了,則值爲true,否則值爲false。當某個鼠標事件發生時,通過檢測這幾個屬性就可以確定用戶是否同時按下了其中的鍵。
摘自《JavaScript高級程序設計》

示例:

<body>
    <P></P>
    <form action=" ">
        <input type="button" value="clickMe">
    </form>
    <script>
        var oP = document.querySelector("p");
        var oInput = document.querySelector("input");    
        oInput.addEventListener("click", function (e) {
            var keys = new Array();
            if (event.shiftKey) {
                keys.push("shift");;
            }
            if (event.ctrlKey) {
                keys.push("ctrl");
            }
            if (event.altKey) {
                keys.push("alt");
            }
            if (event.metaKey) {
                keys.push("meta");
            }
            alert("Keys: " + keys.join(","));
        })
        window.addEventListener("keydown",function(e){//鍵盤事件會講到
            oP.innerText = e.key
        })
    </script>
</body>

在這裏插入圖片描述

(5) 鼠標按鈕的值

對於mousedown 和 mouseup 在其event對象中存在一個button屬性,有如下三個值:
0 表示鼠標左鍵
1 表示鼠標中間
2 表示鼠標右鍵

通過event.button可以知道哪個鼠標按鈕被按下

(6) 記錄點擊次數

detail

單擊或者相繼的發生一次mousedown 和 mouseup 事件算作一次單擊。detail屬性從1開始計數,每次單擊後都會遞增,如果鼠標在mousedown和mouseup之間移動了位置,則detail會被重置。
親測連續且不移動的點擊會遞增,當間隔了一定時間後再次點擊(此時沒有移動),也會清零。另外,在火狐上只能 1、2、3循環,不會遞增。

(7) 滾輪事件的值

wheelDelta

detail (火狐)

當用戶滾動滾輪時,wheeldelta是120的倍數。若向前滾動是120,向後則是 ﹣120(數值根據瀏覽器,在火狐中是4的倍數)

△ 關於移動端的 “鼠標 / 滾輪”

ios和android設備的實現非常特別,因爲這些設備沒有鼠標。在面向iphone和ipad中的開發時,要記住以下幾點:

  • 不支持dblclick事件,雙擊瀏覽器窗口會放大畫面,而且沒有辦法改變該行爲
  • 輕擊可單擊元素觸發mousemove事件。如果此操作會導致內容變化,將不再有其他事件發生;如果屏幕沒有因此變化,那麼會依次發生mousedown、mouseup和click事件。輕擊不可單擊的元素不會觸發任何事件,可單擊的元素時指那些單擊產生默認操作的元素,或者那些已經被指定了onclick事件處理程序的元素
  • mousemove事件也會觸發mouseover和mouseout事件
    摘自《JavaScript高級程序設計》

(四)鍵盤

鍵盤事件與鼠標事件一樣,都支持相同的修改鍵。

△ 事件類型

(1) 按下任意鍵時

keydown

按住不放會重複觸發

(2) 按下字符鍵時

keypress

按住不放會重複觸發

(3) 釋放 / 擡起時

keyup


△ 事件對象

(1) 鍵碼

keyCode

keyCode屬性的值與ASCII碼中會包含一個代碼,與鍵盤上一個特定的鍵對應。

下面貼上鍵碼:
在這裏插入圖片描述

(2) 字符編碼

charCode

這個屬性只有在發生keypress事件時才包含值,而且這個值是按下的那個鍵所代字符的ASCII編碼
這個屬性在DOM3級事件中發生了變化,詳情看下條,如果仍使用了charCode,只會返回 0

(3) 鍵名

key

DOM3級事件中不再包含charCode屬性,而是包含了兩個新屬性:key 和 char

key返回的值是一個字符串。在按下某個字符鍵時,它的值就是相對應的文本。在按下非字符鍵時,它的值是相對應鍵的名,如 “Shift” ,“Alt”。


(五)變動事件

變動事件能在DOM某一部分發生變化時給出提示

(1) 刪除節點時

① 刪除一個節點(裏面不包含子節點時)

事件名:DOMNodeRemoved

在使用removeChild( ) 或 replaceChild( ) 從DOM中刪除節點時,首先會觸發DOMNodeRemoved事件,這個事件的目標(event.target)是被刪除的節點,而event.relatedNode屬性中包含着對目標父節點的引用。這個事件會冒泡,所以可以在DOM的任何層次上面處理它。

示例:

<body>
    <ul>
        <li data-index="0"><p></p></li>
        <li data-index="1"></li>
        <li data-index="2"></li>
        <li data-index="3"></li>
        <li data-index="4"></li>
    </ul>
    <form action=" ">
        <input type="button" value="clickMe">
    </form>
    <script>
        var oInput = document.querySelector("input");
        var oUl = document.querySelector("ul");
        oInput.addEventListener("click",function(){
            oUl.removeChild(oUl.children[0])
        })
        window.addEventListener("DOMNodeRemoved",function(e){
            alert("我刪除的li的索引值是:"+e.target.getAttribute("data-index"))
            alert("它的父元是:"+e.relatedNode.tagName)
        })
    </script>
</body>

在這裏插入圖片描述

② 刪除一個節點(裏面包含子節點時)

注意看下面的引文:

如果被移出的節點包含子節點,那麼在其所有的子節點以及這個被移出的節點上會相繼觸發DOMNodeRemovedFromDocument事件。但因爲這個事件不冒泡,所以只有直接指定給其中一個子節點的事件處理程序纔會被調用。這個事件的目標是相應的子節點或者那個被移出的子節點,除此之外event對象不包含任何信息

事件名:DOMNodeRemovedFromDocument

示例:

html部分與上述代碼相同

    <script>
        var oInput = document.querySelector("input");
        var oUl = document.querySelector("ul");
        oInput.addEventListener("click",function(){
            oUl.removeChild(oUl.children[0])
        })
        window.addEventListener("DOMNodeRemoved",function(e){
            alert("被刪除的li的索引值是:"+e.target.getAttribute("data-index"))
            alert("它的父元是:"+e.relatedNode.tagName)
        })
        //給被刪除的LI綁定時,會觸發 
        oUl.children[0].addEventListener("DOMNodeRemovedFromDocument",function(e){
            alert("我是"+e.target.tagName+"元素,我被刪除了,因爲我裏面有子元素,所以這個事件觸發了")
        })
        //給被刪除的LI的子元素P綁定時,也會觸發
        oUl.children[0].children[0].addEventListener("DOMNodeRemovedFromDocument",function(e){
            alert("我是"+e.target.tagName+"元素,很不幸,因爲我的父元素被刪除了,所以這個事件觸發了")
        })  
    </script>

在這裏插入圖片描述
對白有點呆哈哈哈。

③ 文檔中有元素改變時

事件名:DOMSubtreeModified

刪除節點時,隨着上面兩個事件的觸發,緊隨其後的是DOMSubtreeModified事件。這個事件的目標是被移出節點的父節點;此時的event對象也不會提供與事件相關的任何信息。

(2)插入節點時

抱歉,由於與插入節點相關的事件,跟刪除節點是一個模子裏刻出來的(與刪除事件一一對應),這裏不費力氣闡述了,改日再戰^^

羅列一下事件:

事件名:DOMNodeInserted

事件名:DOMNodeInsertedIntoDocument

事件名:DOMSubtreeModified


(六)HTML5事件

DOM規範沒有涵蓋所有瀏覽器支持的所有事件。很多瀏覽器出於不同的目的——滿足用戶需求或解決特殊問題,還實現了一些自定義的事件。

(1) 鼠標右鍵菜單

事件名:contextmenu

開發人員面臨的主要問題是如何確定應該顯示上下文菜單,以及如何屏蔽與該操作關聯的默認上下文菜單。爲了解決這個問題,就出現了contextmenu事件,用以表示何時應該顯示上下文菜單,以便開發人員取消默認的上下文菜單而提供自定義菜單。

示例:

    <script>
        var oUl = document.querySelector("ul")//可以自己設定ul、li的樣式
        window.addEventListener("contextmenu", function (e) {
            e.preventDefault();
            oUl.style.display = "block";
            oUl.style.left = e.clientX + "px";
            oUl.style.top = e.clientY + "px";
        })
        window.addEventListener("click",function(){
            oUl.style.display = "none";
        })
    </script>

在這裏插入圖片描述
只是一個簡單的示範,不要注意細節^^

(2)用戶離開頁面時提示框

事件名:beforeunload

在用戶離開頁面時詢問是否真想離開


聲明

至此,大多數事件、事件對象都寫到了,還有些許沒有提及的,或者遺忘、漏掉的,後續會補充。

結語:若文章有錯誤的地方,煩請在評論區指出。當然,我會不定時的重新編輯寫過的文章,查錯及優化,希望能將最好的文章展現給讀者。如果覺得文章寫的不錯,請獎勵我一個贊^ ^

我的與此文章相關的文章:

DOM事件處理函數、DOM0,DOM2的優缺點

DOM事件流,冒泡 | 捕獲 | 委託 ,詳解

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章