js事件常用操作、事件流


注冊事件

給元素添加事件,稱為注冊事件或者綁定事件。

注冊事件有兩種方式:傳統方式和方法監聽注冊方式

傳統方式

on開頭的事件,例如onclick

<button onclick=“alert('hi~')”></button>
或
btn.onclick = function() {}

具有唯一性:同一個元素同一個事件只能設置一個處理函數,最后注冊的處理函數將會覆蓋前面注冊的處理函數

方法監聽注冊方式

 eventTarget.addEventListener(type, listener[, useCapture])

eventTarget.addEventListener()方法將指定的監聽器注冊到 eventTarget(目標對象)上,當該對象觸發指定的事件時,就會執行事件處理函數。IE9 之前的 IE 不支持此方法,可使用 attachEvent() 代替

該方法接收三個參數:

  • type:事件類型字符串,比如 click 、mouseover ,注意這里不要帶 on

  • listener:事件處理函數,事件發生時,會調用該監聽函數

  • useCapture:是否捕獲階段,可選參數,是一個布爾值,默認是 false。下面看完DOM事件流方志。

特點:同一個元素同一個事件可以注冊多個監聽器,按注冊順序依次執行

attachEvent 事件監聽方式

eventTarget.attachEvent(eventNameWithOn, callback)

eventTarget.attachEvent()方法將指定的監聽器注冊到 eventTarget(目標對象) 上,當該對象觸發指定的事件時,指定的回調函數就會被執行。

  • eventNameWithOn:事件類型字符串,比如 onclick 、onmouseover ,這里要帶 on

  • callback: 事件處理函數,當目標觸發事件時回調函數被調用

注意:IE8 及早期版本支持

刪除事件

傳統注冊方式eventTarget.onclick = null;

方法監聽注冊方式

eventTarget.removeEventListener(type, listener[, useCapture]);
或
eventTarget.detachEvent(eventNameWithOn, callback);

DOM事件流

事件流描述的是從頁面中接收事件的順序

事件發生時會在元素節點之間按照特定的順序傳播,這個傳播過程即 DOM 事件流。

DOM 事件流分為3個階段:

  1. 捕獲階段

  2. 當前目標階段

  3. 冒泡階段

  • 事件冒泡: IE 最早提出,事件開始時由最具體的元素接收,然后逐級向上傳播到到 DOM 最頂層節點的過程。
  • 事件捕獲: 網景最早提出,由 DOM 最頂層節點開始,然后逐級向下傳播到到最具體的元素接收的過程。

我們向水里面扔一塊石頭,首先它會有一個下降的過程,這個過程就可以理解為從最頂層向事件發生的最具體元素(目標點)的捕獲過程;之后會產生泡泡,會在最低點( 最具體元素)之后漂浮到水面上,這個過程相當於事件冒泡。

事件發生時會在元素節點之間按照特定的順序傳播,這個傳播過程即 DOM 事件流。

注意

  1. JS 代碼中只能執行捕獲或者冒泡其中的一個階段。

  2. onclick 和 attachEvent 只能得到冒泡階段。

  3. addEventListener(type, listener[, useCapture])第三個參數如果是 true,表示在事件捕獲階段調用事件處理程序;如果是 false(不寫默認就是false),表示在事件冒泡階段調用事件處理程序。

  4. 實際開發中我們很少使用事件捕獲,我們更關注事件冒泡。

  5. 有些事件是沒有冒泡的,比如 onblur、onfocus、onmouseenter、onmouseleave

  6. 事件冒泡有時候會帶來麻煩,有時候又會幫助很巧妙的做某些事件,后面講解。

案例

<head>
    <meta charset="UTF-8">
    <title>事件流</title>
    <style>
        .father {
            overflow: hidden;   /*防止嵌套盒子外邊距塌陷*/
            width: 200px;
            height: 200px;
            background-color: #1bc4fb;
            margin: 100px auto;
            text-align: center;
        }
        .son {
            width: 100px;
            height: 100px;
            background-color: pink;
            margin: 50px;
            line-height: 100px;
        }
    </style>
</head>
<body>
    <div class="father">
        <div class="son">
        </div>
    </div>

<script>
    let son = document.querySelector('.son');
    son.addEventListener('click',function () {
        alert('son')
    },true)
    let father = document.querySelector('.father');
    father.addEventListener('click',function () {
        alert('father')
    },true)
</script>
</body>

如上案例,當點擊son盒子時先彈出father還是son呢?

答案是先彈出father,因為addEventListener第三個參數中設置為true,表示處於捕獲階段(document -> html -> body -> father -> son),由外向內,先觸發父盒子的事件再觸發子元素的事件

如果改為false呢?則先彈出的是son

事件對象

什么是事件對象

 eventTarget.onclick = function(event) {} 
或
 eventTarget.addEventListener('click', function(event) {})
 // 這個 event 就是事件對象,我們還喜歡的寫成 e 或者 evt

官方解釋:event 對象代表事件的狀態,比如鍵盤按鍵的狀態、鼠標的位置、鼠標按鈕的狀態。

簡單理解:事件發生后,跟事件相關的一系列信息數據的集合都放到這個對象里面,這個對象就是事件對象event,它有很多屬性和方法

比如:

  1. 誰綁定了這個事件。

  2. 鼠標觸發事件的話,會得到鼠標的相關信息,如鼠標位置。

  3. 鍵盤觸發事件的話,會得到鍵盤的相關信息,如按了哪個鍵。

使用

eventTarget.onclick = function(event) {
 // 這個 event 就是事件對象,我們還喜歡的寫成 e 或者 evt 
 } 
 eventTarget.addEventListener('click', function(event) {
 // 這個 event 就是事件對象,我們還喜歡的寫成 e 或者 evt 
 })

這個 event 是個形參,系統幫我們設定為事件對象,不需要傳遞實參過去。

當我們注冊事件時, event 對象就會被系統自動創建,並依次傳遞給事件監聽器(事件處理函數)。

常見屬性和方法

屬性 描述 DOM
bubbles 返回布爾值,指示事件是否是起泡事件類型。 2
cancelable 返回布爾值,指示事件是否可擁可取消的默認動作。 2
currentTarget 返回其事件監聽器觸發該事件的元素。 2
eventPhase 返回事件傳播的當前階段。 2
target 返回觸發此事件的元素(事件的目標節點)。 2
timeStamp 返回事件生成的日期和時間。 2
type 返回當前 Event 對象表示的事件的名稱。 2
方法 描述 DOM
initEvent() 初始化新創建的 Event 對象的屬性。 2
preventDefault() 通知瀏覽器不要執行與事件關聯的默認動作。例如組織鏈接跳轉 2
stopPropagation() 不再派發事件。

e.target 和 this 的區別:

  • this 是事件綁定的元素, 這個函數的調用者(綁定這個事件的元素)

  • e.target 是事件觸發的元素

事件對象的兼容性方案

事件對象本身的獲取存在兼容問題:

  • 標准瀏覽器中是瀏覽器給方法傳遞的參數,只需要定義形參 e 就可以獲取到。

  • 在 IE6~8 中,瀏覽器不會給方法傳遞參數,如果需要的話,需要到 window.event 中獲取查找。

解決: e = e || window.event;

阻止事件冒泡

事件冒泡:開始時由具體的元素接收,然后逐級向上傳播到到 DOM 最頂層節點。

事件冒泡本身的特性,會帶來壞處,也會帶來的好處,需要我們靈活掌握。

  • 標准寫法:利用事件對象里面的 stopPropagation()方法,e.stopPropagation()

  • 非標准寫法:IE 6-8 利用事件對象 cancelBubble 屬性e.cancelBubble = true;

兼容性問題解決方案

 if(e && e.stopPropagation){
 	e.stopPropagation();
 }else{
	window.event.cancelBubble = true;
 }	

事件委托

 <ul>
     <li>知否知否,應該有彈框在手</li>
     <li>知否知否,應該有彈框在手</li>
     <li>知否知否,應該有彈框在手</li>
     <li>知否知否,應該有彈框在手</li>
     <li>知否知否,應該有彈框在手</li>
 </ul>

上例中若想實現點擊每個 li 都會彈出對話框,以前需要給每個 li 注冊事件,是非常辛苦的,而且訪問 DOM 的次數越多,就會延長整個頁面的交互就緒時間。

解決方案:事件委托

原理

當需要為多個相同子節點設置相同事件時,不再為每個子節點單獨設置,而是為其父節點設置事件監聽器,然后利用冒泡原理影響每個子節點。

以上案例:給 ul 注冊點擊事件,然后利用事件對象的 target 可以定位到當前點擊的 li,點擊 li后,事件會冒泡到 ul 上。

優點:只操作了一次 DOM ,提高了程序的性能

常用鼠標事件

屬性 描述 DOM
onclick 當用戶點擊某個對象時調用的事件句柄。 2
oncontextmenu 在用戶點擊鼠標右鍵打開上下文菜單時觸發
ondblclick 當用戶雙擊某個對象時調用的事件句柄。 2
onmousedown 鼠標按鈕被按下。 2
onmouseenter 當鼠標指針移動到元素上時觸發。 2
onmouseleave 當鼠標指針移出元素時觸發 2
onmousemove 鼠標被移動。 2
onmouseover 鼠標移到某元素之上。 2
onmouseout 鼠標從某元素移開。 2
onmouseup 鼠標按鍵被松開。

鼠標事件對象

屬性 描述 DOM
e.altKey 返回當事件被觸發時,"ALT" 是否被按下。 2
e.button 返回當事件被觸發時,哪個鼠標按鈕被點擊。 2
e.clientX 返回當事件被觸發時,鼠標指針的水平坐標。 2
e.clientY 返回當事件被觸發時,鼠標指針的垂直坐標。 2
e.screenX 返回當某個事件被觸發時,鼠標指針的水平坐標。 2
e.screenY 返回當某個事件被觸發時,鼠標指針的垂直坐標。 2
e.pageX 返回鼠標相當於文檔頁面的 X 坐標,IE9+支持
e.pageY 返回鼠標相當於文檔頁面的 Y 坐標,IE9+支持

案例

//禁止鼠標右鍵
document.addEventListener('contextmenu', function(e) {
	e.preventDefault();
})	

//禁止鼠標選中
document.addEventListener('selectstart', function(e) {
	 e.preventDefault();
 })
//圖片跟隨鼠標移動
 <style>
        img {
            position: absolute;
        }
    </style>
</head>
<body>
<img src="angel.gif">
<script>
    let angel = document.querySelector('img');
    document.addEventListener('mousemove',function (e) {
        angel.style.left = `${e.pageX}px`
        angel.style.top = `${e.pageY}px`
    })
</script>
</body>

① 鼠標不斷的移動,使用鼠標移動事件: mousemove

② 在頁面中移動,給document注冊事件

③ 圖片要移動距離,而且不占位置,我們使用絕對定位即可

④ 核心原理: 每次鼠標移動,我們都會獲得最新的鼠標坐標, 把這個x和y坐標做為圖片的top和left 值就可以移動圖片

常用鍵盤事件

鍵盤事件

屬性 描述 DOM
onkeydown 某個鍵盤按鍵被按下。 2
onkeypress 某個鍵盤按鍵被按下並松開。不識別功能鍵入Ctrl、shift 2
onkeyup 某個鍵盤按鍵被松開。 2

注意:

  1. 如果使用addEventListener 不需要加 on
  2. onkeypress 和前面2個的區別是,它不識別功能鍵,比如左右箭頭,shift 等。
  3. 三個事件的執行順序是: keydown -- keypress --- keyup
  4. onkeydown 和 onkeyup 不區分字母大小寫,onkeypress 區分字母大小寫。在我們實際開發中,我們更多的使用keydown和keyup, 它能識別所有的鍵(包括功能鍵)Keypress 不識別功能鍵

鍵盤事件對象

屬性 描述 DOM
keyCode 返回onkeypress事件觸發的鍵的值的字符代碼,或者 onkeydown 或 onkeyup 事件的鍵的代碼。
  • keyCode屬性能區分大小寫,返回不同的ASCII值


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM