JS中的事件

前言

事件在前端扮演了非常重要的角色,在瀏覽器端,它承擔了用戶交互的很大一部分工作,在服務器端,它充當了一個任務調度者的角色,使得js在單線程的環(huán)境下毫不遜色其他語言。

類型

  • 瀏覽器事件

1.瀏覽器事件是如何發(fā)生的?
答:有兩種主要方式發(fā)生:冒泡和捕獲。
1.1 若事件是從根節(jié)點開始,逐級派送到子節(jié)點,自上而下的過程,這個階段稱為“捕獲階段(Capture)”;
1.2 若事件是由子節(jié)點往根節(jié)點派送,自下而上的過程,這個階段稱為“冒泡階段(Bubble)”。
1.3 一般瀏覽器是先捕獲再處理再冒泡。
1.4 可以手動設置一個事件的發(fā)生方式是冒泡還是捕獲模式,IE不支持設置捕獲模式。
2.事件委托是怎么回事?
答:考慮性能的情況下,父元素代理子元素的所有事件,根據(jù)不同子元素觸發(fā)不同的邏輯。
舉個例子:一個ui元素下有一萬個li元素,總不能每個li元素都綁定一個事件吧,把觸發(fā)邏輯的控制權交給ui元素,那就輕松多了。

<body>
    <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
    </ul>
    <script>
        const ul = document.querySelector("ul")
        ul.addEventListener("click", delegate)

        function delegate(event) {
            console.dir(event.target)
            switch(event.target.textContent){
                case "1":
                alert("第一個li元素")
                break
                case "2":
                alert("第二個li元素")
                break
                case "3":
                alert("第三個li元素")
                break
                default:
                alert("其他li元素")
            }
        }
    </script>
</body>
  • node事件

1.為什么說Node是事件驅動的?
答:因為Node的API大部分都建立在回調基礎上,而這個回調函數(shù)就是Node事件驅動的具體表現(xiàn)。舉個例子:fs.readFile函數(shù)的參數(shù)中必須有一個是回調函數(shù),這個函數(shù)在讀文件的時候,操作系統(tǒng)會類似瀏覽器中監(jiān)聽到了一個“讀文件”事件,然后調用相應的回調。

2.事件循環(huán)是怎么回事?
答:Node官網(wǎng)提供了一副圖來解釋:
┌───────────────────────┐
┌─>│ timers │
│ └──────────┬────────────┘
│ ┌──────────┴────────────┐
│ │ I/O callbacks │
│ └──────────┬────────────┘
│ ┌──────────┴────────────┐
│ │ idle, prepare │
│ └──────────┬────────────┘ ┌───────────────┐
│ ┌──────────┴────────────┐ │ incoming: │
│ │ poll │<─────┤ connections, │
│ └──────────┬────────────┘ │ data, etc. │
│ ┌──────────┴────────────┐ └───────────────
│ │ check │
│ └──────────┬────────────
│ ┌──────────┴────────────┐
└──┤ close callbacks │
└───────────────────────┘
由于JS是單線程的,Node巧妙地把原本多線程的任務轉移給操作系統(tǒng)去做了,簡而言之就是Node將適當?shù)幕卣{添加到輪詢隊列中去,然后經(jīng)過定時器、I/O回調、poll(調查)、check(檢查)、關閉回調循環(huán)執(zhí)行任務,故這個過程又叫事件循環(huán)。它是永遠不會阻塞的。
詳情可以參考阮一峰先生的JavaScript 運行機制詳解:再談Event Loop

  • 自定義事件

1.瀏覽器自定義事件
使用Event()構造

var event = new Event('build');

// 監(jiān)聽事件
elem.addEventListener('build', function (e) { ... }, false);

// 觸發(fā)事件
elem.dispatchEvent(event);

2.Node端自定義事件
使用EventEmiter模塊

const EventEmitter = require('events');

class MyEmitter extends EventEmitter {}

const myEmitter = new MyEmitter();
myEmitter.on('event', () => {
  console.log('an event occurred!');
});
myEmitter.emit('event');

使用

1.監(jiān)聽和取消監(jiān)聽事件

// js文件中
elem.addEventListener('click', function(){...});
// HTML文件中
<button onclick="func()">
//老式js寫法
elem.onclick = function(event){}};

2.阻止事件
寫在事件觸發(fā)的回調函數(shù)里

//取消事件但不阻止傳播
event.preventDefault();
//阻止事件傳播
event.stopPropagation();

3.常見事件種類
3.1 鍵鼠事件

key-mouse
keydown:按下任意按鍵
keypress:除 Shift, Fn, CapsLock 外任意鍵被按住. (連續(xù)觸發(fā))
keyup:釋放任意按鍵
mousedown:在元素上按下任意鼠標按鈕
mouseup:在元素上釋放任意鼠標按鍵
click:在元素上按下并釋放任意鼠標按鍵
dblclick:在元素上雙擊鼠標按鈕
contextmenu:右鍵點擊 (右鍵菜單顯示前).
wheel:滾輪向任意方向滾動
mouseenter:指針移到有事件監(jiān)聽的元素內
mouseover:指針移到有事件監(jiān)聽的元素或者它的子元素內
mousemove:指針在元素內移動時持續(xù)觸發(fā)
mouseleave:指針移出元素范圍外(不冒泡)
mouseout:指針移出元素,或者移到它的子元素上

3.2 拖拽事件

drag
dragenter:被拖動的元素或文本選區(qū)移入有效釋放目標區(qū)
dragstart:用戶開始拖動HTML元素或選中的文本
dragend:拖放操作結束 (松開鼠標按鈕或按下Esc鍵)
dragover:被拖動的元素或文本選區(qū)正在有效釋放目標上被拖動 (在此過程中持續(xù)觸發(fā),每350ms觸發(fā)一次)
dragleave:被拖動的元素或文本選區(qū)移出有效釋放目標區(qū)
drag:正在拖動元素或文本選區(qū)(在此過程中持續(xù)觸發(fā),每350ms觸發(fā)一次)
drop:元素在有效釋放目標區(qū)上釋放

3.3 node事件

文件模塊的讀寫相關事件、HTTP模塊相關事件等等

3.4 其他事件

如資源事件(load/error等)、網(wǎng)絡事件(online)、焦點事件(focus)、會話歷史事件(pageshow/popstate)、
CSS 動畫事件(animationstart)、表單事件(submit)、視圖事件(resize/scroll)、媒體事件(play/pause)、進度事件(load)、值變化事件(input/ValueChange)等等

事件的未來

當多個事件出現(xiàn)在代碼里的時候,邏輯變得不是那么清晰,這個時候把事件轉化成流來處理就非常方便了,具體可以參考RXJS對事件的處理。

總結

編寫前端代碼,離不開處理事件,原生js提供了我們監(jiān)聽事件并執(zhí)行回調函數(shù)的功能(包括node),主流框架也都封裝了事件的相關API,用來實現(xiàn)更強大的功能,比如vue和NG用事件來傳遞子->父組件的數(shù)據(jù),總之,對事件的理解以及如何去利用事件完成需求,我認為,是一個前端工程師的核心技能之一。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 1. 事件冒泡與事件捕獲 事件冒泡和事件捕獲分別由微軟和網(wǎng)景公司提出,這兩個概念都是為了解決頁面中事件流(事件發(fā)生...
    cbw100閱讀 2,818評論 0 8
  • 看到很多文件介紹關于Node.js中的事件循環(huán),但是總是有些地方不是很理解,最近無意中看到了Node官方文檔中對事...
    勤勞的小葉閱讀 3,468評論 0 5
  • 1.背景介紹 1.1什么是事件委托? 事件委托還有一個名字叫事件代理,JavaScript高級程序設計上講:事件委...
    我叫于搞吧閱讀 1,718評論 4 9
  • 什么是事件: 我們可以簡單的把事件理解為瀏覽器的感知系統(tǒng)。比如說:他可以感覺到用戶是否點擊(click)了頁面、鼠...
    張松1366閱讀 7,015評論 1 6
  • 沒事下載了這個軟件,本人嘴拙學淺,上學時作文老是不夠字數(shù),大把年紀了連個對象也沒有,估計一來抒發(fā)下大齡嘴笨苦逼青年...
    Puz閱讀 207評論 0 0

友情鏈接更多精彩內容