前端基礎 — Web事件總結

本文首發於公衆號:符合預期的CoyPan

web中的事件

事件並非JavaScript的核心部分,他們是在瀏覽器的Web Api中定義的。下面列舉的幾種狀況,都屬於發生了事件。javascript

  • 用戶在某個元素上點擊鼠標或懸停光標。
  • 用戶在鍵盤中按下某個按鍵。
  • 用戶調整瀏覽器的大小或者關閉瀏覽器窗口。
  • 一個網頁中止加載。
  • 提交表單。
  • 播放、暫停、關閉視頻。
  • 發生錯誤。

咱們能夠在代碼中使用事件處理器來處理各類事件。html

事件模型

假設咱們有這麼一段html代碼:前端

<html>
    <body>
        <table>
            <tbody>
                <tr>
                    <td>Shady Grove</td>
                    <td>Aeolain</td>
                </tr>
                <tr>
                    <td>Over the River, Charile</td>
                    <td>Dorian</td>
                </tr>
            </tbody>
        </table>
    </body>
</html>

若是咱們點擊over the Rive, Charile,整個事件流程以下:java

clipboard.png

事件會經歷三個階段,上圖中分別由紅色、藍色、綠色標出。第一階段爲紅色,事件流從根元素一直走到點擊的目標元素,這個過程稱爲捕獲。第二階段爲藍色, 稱爲目標階段。這個階段中,會處理點擊事件,爲事件加上各類屬性等。第三階段爲綠色,事件又回從新回到根元素,這個過程稱爲冒泡。在整個事件流中,咱們在事件流通過的任何元素上,都能監聽到該事件,從而進行處理。node

通常建議在冒泡階段處理事件,這樣能夠最大限度的兼容各類瀏覽器。web

注意:blur、focus、load、unload 等幾個事件不會冒泡。

緣由是在於:這些事件僅發生於自身上,而它的任何父節點上的事件都不會產生,全部不會冒泡。瀏覽器

咱們能夠查看事件的bubbles屬性,來判斷該事件是否能夠冒泡。函數

事件處理

EventTarget

EventTarget是一個由能夠接收事件的對象實現的接口,而且能夠爲它們建立偵聽器。Web中的全部事件處理器都是由EventTarget"提供"的。性能

clipboard.png

addEventListener

該方法將指定的監聽器註冊到 EventTarget 上,當該對象觸發指定的事件時,指定的回調函數就會被執行。 事件目標能夠是一個文檔上的元素 Element,DocumentWindow或者任何其餘支持事件的對象 (好比 XMLHttpRequest)。其標準語法以下:spa

target.addEventListener(type, listener[, options]);
target.addEventListener(type, listener[, useCapture]);
  • type: 字符串。表示事件類型,好比: click。
  • listener:函數。事件觸發時的回調函數。這個函數會接受一個Event事件對象。這個Event事件對象中,包含了如下重要的屬性和方法(這裏只列舉出經常使用的)

    屬性
    bubbles 只讀。一個布爾值,表示該事件是否可以在DOM中冒泡。
    cancelBubble 經過在一個事件處理程序返回前設置這個屬性的值爲真,來阻止事件冒泡。
    cancelable 只讀。一個布爾值,用來表示這個事件是否能夠取消。
    currentTarget 只讀。註冊事件監聽的對象。
    target 只讀。對事件起源目標的引用。
    方法 做用
    preventDefault 取消默認事件
    stopPropagation 阻止事件冒泡
  • options :對象。指定一個listener的配置參數。

    屬性
    capture 布爾值。若是爲true,表示該listener會在捕獲過程當中執行。若是爲false,listener會在冒泡過程當中執行。默認爲false。
    once 布爾值。默認爲false。若是爲true,listener只會執行一次,而且執行後會被自動移除。
    passive 布爾值。若是爲true,則沒法調用preventDefault來阻止默認事件。默認爲false。這個屬性有一個須要注意的地方。在safari瀏覽器的頁面滾動事件中,這個值是默認的true。因此要阻止safari中的頁面滾動,須要手動將這個值設爲false。
  • useCapture:布爾值,可選。默認爲false,事件在冒泡過程當中觸發listener
removeEventListener

刪除使用addEventListener註冊到target上的事件。標準語法:

target.removeEventListener(type, listener[, options]);
target.removeEventListener(type, listener[, useCapture]);

爲了提升頁面性能,咱們在處理完某事件,而且不用繼續監聽該事件時,能夠將以前註冊的事件監聽函數移除。須要注意的是,若是註冊事件時,在捕獲或冒泡階段均進行了監聽,那麼移除時須要分別移除。

currentTarget 與 target的區別

在事件處理函數中,咱們常常會使用到事件的這兩個屬性。currentTarget表示註冊事監聽的對象。target表示事件起源的對象。舉個例子:

<div id="father">
     <div id="child1">child1</div>
     <div id="child2">child2</div>
     <div id="child3">child3</div>
</div>

document.getElementById('father').addeventListener('click', function(e){
    console.log(e.currentTarget);
    console.log(e.target);
});

咱們將事件處理函數綁定在father上。如今,若是咱們點擊的是child1,因爲child1是事件源,那麼e.target就是child1。而咱們的事件處理函數是綁定在father上的,因此,e.currentTarget就是father

這一點在開發過程當中須要特別注意。

事件代理

這個概念依賴於這樣一個事實,若是你想要在大量子元素中單擊任何一個均可以運行一段代碼,您能夠將事件監聽器設置在其父節點上,並將事件監聽器氣泡的影響設置爲每一個子節點,而不是每一個子節點單獨設置事件監聽器。舉個例子:

<ul>
    <li>1<li>
    <li>2<li>
    <li>3<li>
    <li>4<li>
    <li>5<li>
    <li>6<li>
    <li>7<li>
    <li>8<li>
    <li>9<li>
</ul>

咱們要實現點擊每個li的時候,輸出li內對應的數字,咱們固然能夠直接在全部的li上分別綁定一個事件。可是這樣會形成內存的浪費。咱們能夠只在ul上綁定一個事件,根據事件的target來獲取當前點擊的li,拿到該li內對應的數字。

document.querySelector('ul').addEventListener('click', function(e){
    if(e.target && e.target.nodeName === "LI") {
        console.log(e.target.innerHTML);
    }
});

自定義事件

最新的DOM標準容許咱們自定義事件。直接看下面的例子。

var fakeNode = document.createElement('Coy'); // 建立一個自定義元素
var evt = document.createEvent('Event'); // 建立一個自定義事件
var evtType = 'test'; // 自定義事件的類型

// 事件監聽函數
fakeNode.addEventListener(evtType, function(e){ 
    console.log(e); // e.type === 'test';
}, false);

// 初始化事件。
// initEvent用法:event.initEvent(type, bubbles, cancelable);
evt.initEvent(evtType, false, false); 

// 向fakeNode派發evt事件
fakeNode.dispatchEvent(evt);

寫在後面

事件,是前端開發中的一個基礎。雖然簡單,可是十分重要。


歡迎關注個人公衆號: 符合預期的CoyPan
作一名符合預期的FE
圖片描述

相關文章
相關標籤/搜索