前端最基礎的就是 HTML+CSS+Javascript
。掌握了這三門技術就算入門,但也僅僅是入門,如今前端開發的定義已經遠遠不止這些。前端小課堂(HTML/CSS/JS
),本着提高技術水平,打牢基礎知識的中心思想,咱們開課啦(每週四)。html
前面咱們已經基本掌握常規的語法語義,以及基本的使用方法。接下來咱們講深刻進去了解其中內在的原理。前端
DOM(Document Object Model——文檔對象模型)是用來呈現以及與任意 HTML 或 XML文檔交互的 API。DOM 是載入到瀏覽器中的文檔模型,以節點樹的形式來表現文檔,每一個節點表明文檔的構成部分(例如:頁面元素、字符串或註釋等等)。
DOM 是萬維網上使用最爲普遍的 API 之一,由於它容許運行在瀏覽器中的代碼訪問文件中的節點並與之交互。節點能夠被建立,移動或修改。 事件監聽器能夠被添加到節點上並在給定事件發生時觸發。
DOM 並非天生就被規範好了的,它是瀏覽器開始實現JavaScript時纔出現的。這個傳統的 DOM 有時會被稱爲 DOM 0。如今, WHATWG 維護DOM現存標準。
-- MDN
既然 DOM
有版本,那麼在他的環境上事件的支持也是有版本的。文檔java
body.onclick
這種定義方式的。面試
addEventListener
方式定義的。正則表達式
取消監聽須要同一引用的函數。舉個栗子segmentfault
// 錯誤案例,兩個方法不是同一引用,致使清除不掉 document.addEventListener('click', function(){}) document.removeEventListener('click', function(){}) // 正確案例,同一引用,能夠清除。 function documentClick(){} document.addEventListener('click', documentClick) document.removeEventListener('click', documentClick)
capture
標準事件:EMCAScript 標準規定事件流包含三個階段,分別爲事件捕獲階段,目標階段,事件冒泡階段。
先存個代碼,以後的例子咱們用這個例子。測試看我這裏的 DEMO瀏覽器
<html onclick="alert('html')"> <body onclick="alert('body')"> <a onclick="alert('a')">click</a> </body> </html>
捕獲階段:由外到內,觸發規律爲 html > body > a
。
若是想在捕獲階段就觸發,須要傳入參數 {capture: true}
微信
冒泡階段:由內到外,觸發規律爲 a > body > html
這個階段執行是 W3C
默認的,等價於 {capture: false}
cookie
圖片來源-https://www.w3.org/TR/DOM-Lev...
事件的捕獲階段 > 處於目標階段 > 事件的冒泡階段 > 事件的默認行爲
這裏爲何要強調這個順序呢?session
e.preventDefault()
來阻止。passive
爲 false
。passive: Boolean
,設置爲 true
時,表示 listener
永遠不會調用 preventDefault()
。若是 listener
仍然調用了這個函數,客戶端將會忽略它並拋出一個控制檯警告。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 時有效 |
event.cancelBubble=true;
//阻止事件冒泡event.returnValue=false;
//阻止事件的默認行爲window.event
DOM event 子類,根據不一樣的事件類型,返回的對象會有些許不一樣,好比 Mouse
類型的,就會有單擊座標之類的。 KeyboardEvent
之類的就會有按鍵之類的。
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);
首先,咱們要牢記一件事情 js 是單線程Event Loop
中文叫事件循環。是瀏覽器內部的一種機制,javaScript 單線程運行時如何不阻塞 UI
。Javascript
有一個 main thread 主線程
和 call-stack 調用棧(執行棧)
,全部的任務都會被放到調用棧(棧採用的是後進先出的規則)等待主線程執行。
在 JavaScript
中,任務被分爲兩種,一種宏任務(MacroTask)也叫Task,一種叫微任務(MicroTask)。
<script>
、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}
MicroTasks
步驟:
MicroTask
檢查點MicroTask
檢查點標誌爲 true
當事件循環 MicroTask
不爲空時:
MicroTask
改變狀態MicroTask
。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
MacroTasks
是否有數據?MacroTasks
中第一個。console.log('setTimeout');
輸出。DOM
事件setTimeout
XHR
Promise
事件機制