1. 程式人生 > 實用技巧 >面試 03-DOM事件的總結

面試 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-事件委託》