事件傳遞機制
DOM
DOM 全名為 Document Object Model 中文翻譯為 文件物件模型。
其實就是把 HTML 文件內的標籤、文字、圖片等等都定義成物件,而這些物件會形成一個樹狀結構,並且可以利用 JavaScript 來對 HTML 文件進操作和互動。
DOM 節點 (node)
在 DOM 中,節點可以分成四種:
Document
HTML 檔的開端,所有的一切都會從 Document 開始往下進行
Element
文件內的各個標籤,像是 <div>
、<p>
等等各種 HTML Tag 都是被歸類在 Element 裡面
Text
各個標籤內的文字內容
Attribute
各個標籤內的相關屬性,像是 class、href 等等
捕獲與冒泡
JavaScript 是事件驅動的程式語言,也就是說,當 user 對網頁做了指定動作,才會觸發程式執行動作。
前面提到 DOM 會以物件形式定義 HTML 內的元件,這些物件會連結形成一個樹狀節構,而為了操控這些物件節點,需要透過 DOM 裡面的事件傳遞機制。
當我們要獲得一個 DOM 的 click 事件時,會這樣寫:
1 | const btn = document.getElementById('.btn') |
裡面的 e
包含許多關於這次事件的相關參數,其中一個參數 eventPhase
表示這個事件在哪一個階段(Phase)觸發。
事件傳遞機制總共分為三大階段:
捕獲階段 (Capture Phase)
在捕獲階段,DOM 的事件會從根節點 (window) 開始往下尋找目標 (target),這個過程稱為捕獲階段 (CAPTURING_PHASE)。目標階段 (Target Phase)
在找到目標的時候,就會是目標階段 (AT_TARGET)。冒泡階段 (Bubbling Phase)
從子節點一路回傳到根節點,這個階段就稱作冒泡階段 (BUBBLING_PHASE)。
// PhaseType
const unsigned short CAPTURING_PHASE = 1;
const unsigned short AT_TARGET = 2;
const unsigned short BUBBLING_PHASE = 3;
用以下範例說明,在一般情況下,當點擊了 a
連結,因為傳遞機制的關係,其實會連同外層的<li>
、<ul>
也一起被觸發。
從最外層的 <ul>
開始往下捕獲,然後找到目標 <a>
,接著再冒泡回到 <ul>
。
停止事件傳遞 stopPropagation
在開發程式的過程中,可以加上 e.stopPropagation()
來停止冒泡事件。
用以上範例說明,我在 <a>
連結裡加入 e.stopPropagation()
,點擊按鈕後會沒有反應,再對 <li>
點擊時會顯示前一個動作回傳的內容。
從回傳結果可以發現,當點擊 <a>
連結時,因為停止冒泡的關係,所以事件傳遞只到找到目標就停止,並沒有繼續回傳事件。而第二次點擊的 <li>
沒有加上 e.stopPropagation()
,所以會繼續冒泡,完成整個傳遞過程。
取消預設行為 preventDefault
stopPropagation()
常和 preventDefault()
搞混,但其實兩者沒什麼關係。preventDefault()
也是 e
的點擊事件參數之一,功能是取消瀏覽器的預設行為。
舉例來說,如果想要點擊 <a>
連結又不想讓預設的超連結轉跳到別的網頁,就可以加上 e.preventDefault()
。
1 | link.addEventListener("click", function (e) { |