瀏覽器中的事件捕獲和冒泡

js是一門事件驅動的編程語言,事件一般有多種,好比說網絡事件,IO事件,定時事件,點擊事件等等。 在這裏先只關注下前端瀏覽器中的事件。前端

什麼事件

如同字面意思,事件就表明了一件事或一個動做,瀏覽器中的事件有哪些node

window事件 form事件 keyboard事件 mouse事件 media事件
afterprint onblur onkeydown onclick onabort
beforeprint onchange onkeypress ondbclick oncanplay
onload oncontextmenu onkeyup ondrag oncanplaythrough
onunload onformchange ongragend ondurationchange
onbeforeunload onforminput ondragenter onemptied
onerror onforcus ondragleave onended
onhaschange oninput ondragover onerror
onmessage oninvalid ondragstart onloadeddata
onoffline onreset ondrop onloadedmetadata
ononline onselect onmousedown onloadstart
onpagehide onsubmit onmousemove onpause
onpageshow onmouseout onplay
onpopstate onmouseover onplaying
onredo onmouseover onprogress
onresize onmoseup onratechange
onstorage onmosewhell onreadystatechange
onundo onscroll onseeked
onunload onseeking
onstalled
onsuspend
ontimeupdate
onvolumechange
onwaiting

事件觸發過程

從上面各方各面的事件上咱們能夠看出瀏覽器衝加載到退出那一刻,無時不刻不在觸發事件,那麼事件觸發是怎樣的一個流程呢?編程

輸入圖片說明

當dom節點發生了某些操做時,就會有一個事件發射出去,這個事件從window發出,不斷通過下級節點知道目標節點,這個階段稱爲捕獲階段。全部通過的節點都會觸發這個事件,捕獲階段的任務就是創建事件傳遞線路,以便後面冒泡階段順着該線路返回至window。監聽該階段的事件,能夠經過把addEventListener第三個參數設爲true瀏覽器

node.addEventListener('click', function() {}, true);

當事件傳遞到目標節點哪裏,最終會在目標節點上觸發這個事件,這個就是目標階段(事件觸發的目標老是最最底層的節點:如<p>hello <em>world</em></p>,目標節點能夠是p也能夠是em)網絡

當事件到達目標節點以後,會沿捕獲階段的路線原路返回,這個階段稱爲冒泡階段,一樣沿途全部的節點都會再次觸發該事件。dom

監聽父節點

由事件的觸發機制咱們能夠看到,沿途全部的父節點都會被觸發兩次該事件,一次是捕獲階段,一次是冒泡階段。編程語言

node.addEventListener('click', functioon() {console.log('hello')}, true) ; //捕獲階段
node.addEventListener('click', function() {console.log('world')}, false); //冒泡階段

因此咱們能夠經過冒泡機制來監聽父節點的事件,實現監聽子節點,尤爲是當子節點很是多的時候ide

注:因爲IE瀏覽器不支持在捕獲階段監聽事件,全部一般只用冒泡階段來監聽事件。函數

冒泡的煩惱

事件的冒泡機制,雖然很好,但有些場合並不使用。在比較複雜的應用中,監聽比較複雜,咱們可能只但願監聽發生具體事件的節點,這個時候就要阻止冒泡spa

阻止冒泡可使用事件對象的stopPropagation方法

node.addEventListener('click', function(e) {
    //operations
    e.stopPropagation();    
}, false);

事件對象

在阻止冒泡時咱們使用到了事件對象,那麼事件對象是什麼? 當一個事件被觸發的時候,會建立一個事件對象,這裏麪包含了一些有用的屬性和方法,事件對象會做爲回調函數的的第一個參數(如同node回調第一個參數永遠是error同樣)

<body>
  <div class="one">
    <div class="two">
      <div class="three">

      </div>
    </div>
  </div>
</body>

node.addEventListener('click', function(e) {
    console.log('事件對象', e)
}, false);

事件對象的屬性和方法等(方法大部分上是對屬性的get方法)

屬性 描述 方法 描述
altKey addEventListener 添加事件綁定
bubbles 是否在冒泡階段觸發 removeEventListener 刪除事件綁定
button stopPropagation 中止冒泡
buttons preventDefault 禁止瀏覽器默認行爲
cancelBubble dispatchEvent 手動觸發事件(var event=new Event('click'); element.dispatchEvent(event)
cancelable 是否能夠調用proventDefault來禁止
clientX
clientY
composed
ctrlKey
currentTarget
defaultPrevented 是否禁止了默認行爲
detail
eventPhase 當前事件觸發在什麼階段。none:0;捕獲:1;目標:2;冒泡:3
fromElement
isTrusted 瀏覽器觸發(用戶真實操做觸發),仍是 JavaScript 代碼觸發的
layerX
layerY
metaKey
movementX
movementY
offsetX
offsetY
pageX 頁面的座標
pageY 頁面的座標
path 事件路徑
relatedTarget
returnValue
screenX
screenY
shiftKey
sourceCapabilities
srcElement ie6-8 的觸發事件的 dom 元素,非標準
target 觸發的目標節點
timeStamp 返回事件發生時的時間戳
toElement
type 事件類型
view
which
x
y

事件代理

傳統的事件綁定存在兩個不足的地方:1)須要綁定不少個eventhandler 2)事件沒法綁定後加入的節點。 事件的代理或委託就是事件觸發過程當中冒泡機制和事件對象的應用,j簡單的結構以下

document.getElementById("parent-list").addEventListener("click",function(e) {
	// e.target是被點擊的元素!
	// 若是被點擊的是li元素
	if(e.target && e.target.nodeName == "li") {
		// 找到目標,輸出ID!
		console.log("find");
	}
});
相關文章
相關標籤/搜索