摘要:事件監聽器可以被添加到節點上并在給定事件發生時觸發。可以選擇觸發階段冒泡捕獲事件機制標準事件標準規定事件流包含三個階段,分別為事件捕獲階段,目標階段,事件冒泡階段。返回其事件監聽器觸發該事件的元素。清理事務設置檢查點的標志為。
前端最基礎的就是 HTML+CSS+Javascript。掌握了這三門技術就算入門,但也僅僅是入門,現在前端開發的定義已經遠遠不止這些。前端小課堂(HTML/CSS/JS),本著提升技術水平,打牢基礎知識的中心思想,我們開課啦(每周四)。
前面我們已經基本掌握常規的語法語義,以及基本的使用方法。接下來我們講深入進去了解其中內在的原理。
今天我們要講什么?事件機制
事件對象(Event)
event loop
DOM (與事件的關系,看不看無所謂)DOM(Document Object Model——文檔對象模型)是用來呈現以及與任意 HTML 或 XML文檔交互的 API。DOM 是載入到瀏覽器中的文檔模型,以節點樹的形式來表現文檔,每個節點代表文檔的構成部分(例如:頁面元素、字符串或注釋等等)。
DOM 是萬維網上使用最為廣泛的 API 之一,因為它允許運行在瀏覽器中的代碼訪問文件中的節點并與之交互。節點可以被創建,移動或修改。事件監聽器可以被添加到節點上并在給定事件發生時觸發。
DOM 并不是天生就被規范好了的,它是瀏覽器開始實現JavaScript時才出現的。這個傳統的 DOM 有時會被稱為 DOM 0。現在, WHATWG 維護DOM現存標準。
-- MDN
既然 DOM 有版本,那么在他的環境上事件的支持也是有版本的。文檔
DOM 事件(0 級)body.onclick 這種定義方式的。
不可以多次監聽事件,因為是賦值的方式,下次賦值會覆蓋。
只可以在冒泡階段觸發
DOM 事件(2 級)addEventListener 方式定義的。
可以多次監聽,切按監聽順序執行回調(有序)
取消監聽需要同一引用的函數。舉個栗子
// 錯誤案例,兩個方法不是同一引用,導致清除不掉 document.addEventListener("click", function(){}) document.removeEventListener("click", function(){}) // 正確案例,同一引用,可以清除。 function documentClick(){} document.addEventListener("click", documentClick) document.removeEventListener("click", documentClick)
可以選擇觸發階段(冒泡&捕獲) capture
事件機制標準事件:EMCAScript 標準規定事件流包含三個階段,分別為事件捕獲階段,目標階段,事件冒泡階段。
先存個代碼,之后的例子我們用這個例子。測試看我這里的 DEMO
click事件捕獲階段
捕獲階段:由外到內,觸發規律為 html > body > a。
如果想在捕獲階段就觸發,需要傳入參數 {capture: true}
冒泡階段:由內到外,觸發規律為 a > body > html
這個階段執行是 W3C 默認的,等價于 {capture: false}
圖片來源-https://www.w3.org/TR/DOM-Lev...
事件的捕獲階段 > 處于目標階段 > 事件的冒泡階段 > 事件的默認行為
這里為什么要強調這個順序呢?
因為默認行為是在最后面,所以我們都可以用 e.preventDefault() 來阻止。
基于上條的阻止默認事件。在移動端滑動時,阻止默認事件需要手動設置 passive 為 false。
passive: Boolean,設置為 true 時,表示 listener 永遠不會調用 preventDefault()。如果 listener 仍然調用了這個函數,客戶端將會忽略它并拋出一個控制臺警告。
我們真正單擊的元素的事件觸發不在冒泡和捕獲階段,而在目標階段觸發。 DEMO-冒泡&捕獲階段觸發事件,可以看到,他是通過定義時的先后順序來觸發的。
事件對象(Event)Event 對象--mdn
事件對象(屬性&方法)key | 類型 | 描述 |
---|---|---|
bubbles | boolean | 是否冒泡 |
cancelable | boolean | 是否可以取消的默認動作。 |
currentTarget | Element | 返回其事件監聽器觸發該事件的元素。(this 的真實指向) |
eventPhase | Intenger | 返回事件傳播的當前階段 |
target | Element | 返回觸發此事件的元素。(事件的目標節點) |
timeStamp | Date | 觸發的時間戳 |
type | String | 事件名稱。 |
isTrusted | boolean | 該事件是否是瀏覽器生成(true 代表是,false 代表是開發人員創建 |
preventDefault | Function | 取消事件的默認行為在 cancelable=true 時有效 |
stopPropagation | Function | 取消事件的捕獲或者冒泡行為在 bubbles=true 時有效 |
IE: event.cancelBubble=true; //阻止事件冒泡
IE: event.returnValue=false; //阻止事件的默認行為
獲取事件 window.event
事件類型(分類、Event對象之類)DOM event 子類,根據不同的事件類型,返回的對象會有些許不同,比如 Mouse 類型的,就會有單擊坐標之類的。 KeyboardEvent 之類的就會有按鍵之類的。
new 一個事件對象CustomEvent() --mdn
document.body.onclick=function(e){console.log(e)} var btn=document.body; var event= new CustomEvent("click"); btn.dispatchEvent(event);
其實這里我們可以自定義事件的名稱,然后我們就可以實現一個發布訂閱的功能。
document.addEventListener("bus", function(e) { console.log(e, e.detail) }); var event = new CustomEvent("bus", {detail: {LN_type: "lilnong.top"}}); document.dispatchEvent(event);event loop (事件循環)
首先,我們要牢記一件事情 js 是單線程
Event Loop 中文叫事件循環。是瀏覽器內部的一種機制,javaScript 單線程運行時如何不阻塞 UI。
Javascript 有一個 main thread 主線程和 call-stack 調用棧(執行棧),所有的任務都會被放到調用棧(棧采用的是后進先出的規則)等待主線程執行。
在 JavaScript 中,任務被分為兩種,一種宏任務(MacroTask)也叫Task,一種叫微任務(MicroTask)。
MacroTask(宏任務)、setTimeout、setInterval、setImmediate、I/O、UI Rendering。
異步任務會在有了結果后,將注冊的回調函數放入任務隊列中等待主線程空閑的時候(調用棧被清空),被讀取到棧內等待主線程的執行。
Process.nextTick(Node獨有)、Promise、MutationObserver
每個宏任務執行完畢后,會檢查 microTask 隊列是否有回調,會按照先入先出的規則執行,都執行完再執行宏任務,如此循環。
棧采用的是后進先出的規則,這里我們調用 a(),a() 內部會調用 aa(), aa() 內部又調用 aa()。
function a(){return aa()} function aa(){return aaa()} function aaa(){return 1}
a 進棧
aa 進棧
aaa 進棧
aaa 出棧
...
事件循環的進程模型選擇任務隊列中最先進入的任務,如果任務隊列為空,則執行跳轉到微任務(MicroTask)的執行步驟
任務設置為已選擇任務
執行任務
任務設置為空
運行完成的任務從任務隊列中刪除
MicroTasks 步驟:
進入 MicroTask 檢查點
設置 MicroTask 檢查點標志為 true
當事件循環 MicroTask 不為空時:
選擇最先進入隊列的任務,
設置為已選擇的任務
運行
將已經執行完成的 MicroTask 改變狀態
移出 MicroTask。
清理IndexDB事務
設置 MicroTask 檢查點的標志為false。
更新界面渲染。
返回第一步。
舉個栗子(常問無聊題)console.log("script start"); setTimeout(function() { console.log("setTimeout"); }, 0); new Promise(function(reslove){ console.log("Promise-start") reslove(); }).then(function() { console.log("Promise-end"); }) console.log("script end");
結構應該沒錯
任務入棧(代碼塊)
console.log("script start"); 棧中,同步代碼,直接輸出
function() {console.log("setTimeout");} 入 MacroTask
new Promise 同步代碼,執行
入棧 function(reslove){console.log("Promise-start");reslove();}
執行 console.log("Promise-start");
出棧
.then(function() {console.log("Promise-end");}) 進 MicroTask
console.log("script end"); 同步代碼,輸出
當前執行完出棧,判斷 MicroTasks
執行 console.log("Promise-end");
完成所有 MicroTasks
渲染 UI
MacroTasks是否有數據?
執行 MacroTasks 中第一個。
console.log("setTimeout"); 輸出。
異步事件(消息)DOM 事件
setTimeout
XHR
Promise
總結
事件機制
當前執行塊
當前執行塊的微任務隊列
宏任務隊列
Event 事件級別
addEventListener 要主要保存 function 的引用,用于解綁
隊列,先進先出(想起了梗,吃多了拉)
堆棧,先進后出(想起了梗,吃多了吐)
觸發階段 捕獲>目標>冒泡
Event 對象,針對不同的類型,有自己獨特的屬性。
微信公眾號:前端linong 初級階段文章目錄前端培訓-初級階段(17) - 數據存儲(cookie、session、stroage)
前端培訓-初級階段(13) - 正則表達式
前端培訓-初級階段(13) - 類、模塊、繼承
前端培訓-初級階段(13) - ECMAScript (內置對象、函數)
前端培訓-初級階段(13) - ECMAScript (語法、變量、值、類型、運算符、語句)
前端培訓-初級階段(13、18)
前端培訓-初級階段(9 -12)
前端培訓-初級階段(5 - 8)
前端培訓-初級階段(1 - 4)
資料前端培訓目錄、前端培訓規劃、前端培訓計劃
JavaScript系列----事件機制
事件參考--mdn
tasks-microtasks-queues-and-schedules
一次弄懂Event Loop(徹底解決此類面試問題) --光光同學-juejin
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/104812.html
摘要:事件監聽器可以被添加到節點上并在給定事件發生時觸發。可以選擇觸發階段冒泡捕獲事件機制標準事件標準規定事件流包含三個階段,分別為事件捕獲階段,目標階段,事件冒泡階段。返回其事件監聽器觸發該事件的元素。清理事務設置檢查點的標志為。 前端最基礎的就是 HTML+CSS+Javascript。掌握了這三門技術就算入門,但也僅僅是入門,現在前端開發的定義已經遠遠不止這些。前端小課堂(HTML/C...
摘要:前端最基礎的就是。幫助從舊的事件方法轉換,和。方法移除用綁定的事件處理程序。特定的事件處理程序可以被移除元素上提供事件名稱,命名空間,處理函數。用于過濾器的觸發事件的選擇器元素的后代。事件觸發模擬觸發原生使用觸發。 前端最基礎的就是 HTML+CSS+Javascript。掌握了這三門技術就算入門,但也僅僅是入門,現在前端開發的定義已經遠遠不止這些。前端小課堂(HTML/CSS/JS)...
摘要:前端最基礎的就是。幫助從舊的事件方法轉換,和。方法移除用綁定的事件處理程序。特定的事件處理程序可以被移除元素上提供事件名稱,命名空間,處理函數。用于過濾器的觸發事件的選擇器元素的后代。事件觸發模擬觸發原生使用觸發。 前端最基礎的就是 HTML+CSS+Javascript。掌握了這三門技術就算入門,但也僅僅是入門,現在前端開發的定義已經遠遠不止這些。前端小課堂(HTML/CSS/JS)...
閱讀 2640·2021-11-22 15:24
閱讀 1370·2021-11-17 09:38
閱讀 2748·2021-10-09 09:57
閱讀 1193·2019-08-30 15:44
閱讀 2439·2019-08-30 14:00
閱讀 3539·2019-08-30 11:26
閱讀 2936·2019-08-29 16:28
閱讀 746·2019-08-29 13:56