面試 03-DOM事件的總結
03-DOM事件的總結
#前言
要學習事件的基礎內容,請看先本人之前的基礎文章:
-
《04-JavaScript基礎/27-事件物件Event》
-
《04-JavaScript基礎/28-事件捕獲和事件冒泡》
-
《04-JavaScript基礎/29-事件委託》
知識難度不大,只是大家需要系統地學習。
知識點主要包括以下幾個方面:
- 基本概念:DOM事件的級別
面試不會直接問你,DOM有幾個級別。但會在題目中體現:“請用DOM2 ....”。
- DOM事件模型、DOM事件流
面試官如果問你“DOM事件模型”,你不一定知道怎麼回事。其實說的就是捕獲和冒泡。
DOM事件流,指的是事件傳遞的三個階段。
- 描述DOM事件捕獲的具體流程
講的是事件的傳遞順序。引數為false(預設)、引數為true,各自代表事件在什麼階段觸發。
能回答出來的人,寥寥無幾。也許有些人可以說出一大半,但是一字不落的人,極少。
- Event物件的常見應用(Event的常用api方法)
DOM事件的知識點,一方面包括事件的流程;另一方面就是:怎麼去註冊事件,也就是監聽使用者的互動行為。第三點:在響應時,Event物件是非常重要的。
- 自定義事件(非常重要)
一般人可以講出事件和註冊事件,但是如果讓你講自定義事件,能知道的人,就更少了。
- 事件委託
業務中經常用到。
下面分別講解。
#DOM事件的級別
DOM事件的級別,準確來說,是DOM標準定義的級別。包括:
DOM0的寫法:
element.onclick = function () {
}
上面的程式碼是在 js 中的寫法;如果要在html中寫,寫法是:在onclick屬性中,加 js 語句。
DOM2的寫法:
element.addEventListener('click', function () {
}, false);
【重要】上面的第三引數中,true表示事件在捕獲階段觸發,false表示事件在冒泡階段觸發(預設)。如果不寫,則預設為false。
DOM3的寫法:
element.addEventListener('keyup', function () {
}, false);
DOM3中,增加了很多事件型別,比如滑鼠事件、鍵盤事件等。
PS:為何事件沒有DOM1的寫法呢?因為,DOM1標準制定的時候,沒有涉及與事件相關的內容。
總結:關於“DOM事件的級別”,能回答出以上內容即可,不會出題目讓你做。
#DOM事件模型、DOM事件流
#DOM事件模型
DOM事件模型講的就是捕獲和冒泡,一般人都能回答出來。
-
捕獲:從上往下。
-
冒泡:從下(目標元素)往上。
#DOM事件流
DOM事件流講的就是:瀏覽器在於當前頁面做互動時,這個事件是怎麼傳遞到頁面上的。
類似於Android裡面的事件傳遞。
完整的事件流,分三個階段:
-
(1)捕獲:從 window 物件傳到 目標元素。
-
(2)目標階段:事件通過捕獲,到達目標元素,這個階段就是目標階段。
-
(3)冒泡:從目標元素傳到 Window 物件。
#描述DOM事件捕獲的具體流程
很少有人能說完整。
#捕獲的流程
說明:捕獲階段,事件依次傳遞的順序是:window --> document --> html--> body --> 父元素、子元素、目標元素。
PS1:第一個接收到事件的物件是window(有人會說body,有人會說html,這都是錯誤的)。
PS2:JS中涉及到DOM物件時,有兩個物件最常用:window、doucument。它們倆也是最先獲取到事件的。
程式碼如下:
window.addEventListener("click", function () {
alert("捕獲 window");
}, true);
document.addEventListener("click", function () {
alert("捕獲 document");
}, true);
document.documentElement.addEventListener("click", function () {
alert("捕獲 html");
}, true);
document.body.addEventListener("click", function () {
alert("捕獲 body");
}, true);
fatherBox.addEventListener("click", function () {
alert("捕獲 father");
}, true);
childBox.addEventListener("click", function () {
alert("捕獲 child");
}, true);
補充一個知識點:
在 js中:
-
如果想獲取
body
節點,方法是:document.body
; -
但是,如果想獲取
html
節點,方法是document.documentElement
。
#冒泡的流程
與捕獲的流程相反
#Event物件的常見 api 方法
使用者做的是什麼操作(比如,是敲鍵盤了,還是點選滑鼠了),這些事件基本都是通過Event物件拿到的。這些都比較簡單,我們就不講了。我們來看看下面這幾個方法:
#方法一
event.preventDefault();
解釋:阻止預設事件。
比如,已知<a>
標籤綁定了click事件,此時,如果給<a>
設定了這個方法,就阻止了連結的預設跳轉。
#方法二:阻止冒泡
這個在業務中很常見。
有的時候,業務中不需要事件進行冒泡。比如說,業務這樣要求:單擊子元素做事件A,單擊父元素做事件B,如果不阻止冒泡的話,出現的問題是:單擊子元素時,子元素和父元素都會做事件A。這個時候,就要用到阻止冒泡了。
w3c的方法:(火狐、谷歌、IE11)
event.stopPropagation();
IE10以下則是:
event.cancelBubble = true;
相容程式碼如下:
box3.onclick = function (event) {
alert("child");
//阻止冒泡
event = event || window.event;
if (event && event.stopPropagation) {
event.stopPropagation();
} else {
event.cancelBubble = true;
}
}
上方程式碼中,我們對box3進行了阻止冒泡,產生的效果是:事件不會繼續傳遞到 father、grandfather、body了。
#方法三:設定事件優先順序
event.stopImmediatePropagation();
這個方法比較長,一般人沒聽說過。解釋如下:
比如說,我用addEventListener給某按鈕同時註冊了事件A、事件B。此時,如果我單擊按鈕,就會依次執行事件A和事件B。現在要求:單擊按鈕時,只執行事件A,不執行事件B。該怎麼做呢?這是時候,就可以用到stopImmediatePropagation
方法了。做法是:在事件A的響應函式中加入這句話。
大家要記住 event 有這個方法。
#屬性4、屬性5(事件委託中用到)
event.currentTarget //當前所繫結的事件物件。在事件委託中,指的是【父元素】。
event.target //當前被點選的元素。在事件委託中,指的是【子元素】。
上面這兩個屬性,在事件委託中經常用到。
總結:上面這幾項,非常重要,但是容易弄混淆。
#自定義事件
自定義事件的程式碼如下:
var myEvent = new Event('clickTest');
element.addEventListener('clickTest', function () {
console.log('smyhvae');
});
//元素註冊事件
element.dispatchEvent(myEvent); //注意,引數是寫事件物件 myEvent,不是寫 事件名 clickTest
上面這個事件是定義完了之後,就直接自動觸發了。在正常的業務中,這個事件一般是和別的事件結合用的。比如延時器設定按鈕的動作:
var myEvent = new Event('clickTest');
element.addEventListener('clickTest', function () {
console.log('smyhvae');
});
setTimeout(function () {
element.dispatchEvent(myEvent); //注意,引數是寫事件物件 myEvent,不是寫 事件名 clickTest
}, 1000);
#事件委託
參考本人這篇文章的最後一段:
- 《04-JavaScript基礎/29-事件委託》