由W3C規定的DOM2標準中,一次事件的完整過程包括三步:捕獲→執行目標元素的監聽函數→冒泡,在捕獲和冒泡階段,會依次檢查途徑的每一個節點,若是該節點註冊了相應的監聽函數,則執行監聽函數。如下面的HTML結構爲例:javascript
<div id="parentdiv"> 父親 <div id="childdiv">孩子</div> </div>
執行的流程應該是這樣的:java
下面是一組例子,分別點擊孩子節點能夠清楚的看到第三個參數的影響:web
父親瀏覽器
孩子框架
父親節點的監聽函數在捕獲階段執行:異步
var parent1 = document.getElementById(‘parentdiv1′); var child1 = document.getElementById(‘childdiv1′); parent.addEventListener(‘click’,function(){alert(‘父親被點擊了’);},true);//第三個參數爲true child.addEventListener(‘click’,function(){alert(‘孩子被點擊了’);},false);
父親函數
孩子
父親節點的監聽函數在冒泡階段執行:性能
var parent2 = document.getElementById(‘parentdiv2′); var child2 = document.getElementById(‘childdiv2′); parent.addEventListener(‘click’,function(){alert(‘父親被點擊了’);},false);//第三個參數爲false child.addEventListener(‘click’,function(){alert(‘孩子被點擊了’);},false);
父親this
孩子spa
父親節點的監聽函數在捕獲冒泡階段都執行:
var child3 = document.getElementById(‘childdiv3′); parent.addEventListener(‘click’,function(){alert(‘父親被點擊了’);},true);//第三個參數爲true parent.addEventListener(‘click’,function(){alert(‘父親被點擊了’);},false);//第三個參數爲false child.addEventListener(‘click’,function(){alert(‘孩子被點擊了’);},false);
若是不想讓事件向上冒泡,能夠在監聽函數中調用event.stopPrapagation()來完成,這樣父親節點就捕捉不到該事件了。在實際的開發中,這一用處仍是挺多的。
知道了事件的捕獲冒泡機制,咱們能夠利用它來實現更方便的程序控制,事件委託即是最典型的應用之一。下面來講說javascript中的事件委託機制。什麼叫委託呢?想一想咱們現實生活中,本身不想幹的事,讓別人來幫忙完成,這就是把事情「委託」給別人。Javascript的事件委託機制也是這個道理,原本一個監聽函數要處理節點a觸發的事件,如今把這個監聽函數綁定到節點a的父層節點上,讓它的父輩來完成事件的監聽,這樣就把事情「委託」了過去。在父輩元素的監聽函數中,可經過event.target屬性拿到觸發事件的原始元素,而後再對其進行相關處理。
那這樣作有什麼好處呢?最大的用處即是監聽動態增長的元素。好比咱們如今有這樣的需求,點擊下面每一個列表項彈出各自的內容,如今隨着web應用的盛行,網頁中使用異步請求來動態加載節點已經變的很廣泛,因此咱們點擊下方的按鈕要在列表中增長一項,而且點擊新增長的節點也要彈出內容。HTML結構以下:
<ol id="olist"> <li>列表內容1</li> <li>列表內容2</li> <li>列表內容3</li> <li>列表內容4</li> <li>列表內容5</li> </ol>
若咱們使用以前的監聽器綁定方式,須要遍歷全部的li元素並監聽,代碼應該是這樣的:
var listArray = document.getElementById('olist').childNodes; for(var i=0;i<listArray.length;i++){ listArray[i].addEventListener('click',function({ alert(this.innerText); }); }
運行效果以下:
列表內容1
列表內容2
列表內容3
列表內容4
列表內容5
能夠發現當新增元素後,點擊它並無彈出內容。那是固然的了,由於咱們並無給新增的元素綁定監聽器,爲了實現點擊新增元素也彈出內容,咱們不得不在每次新增一個元素後,再進行一次綁定。加一個綁一個,加一個綁一個,累不累啊!你不累瀏覽器都累了!這樣作致使的性能開銷是可想而知的,並且瀏覽器還要維繫n多元素與應的監聽函數的映射關係,會佔用大量內存。
面對這樣拖沓冗雜的代碼,你是否是已經不能忍,來看看使用事件委託的效果,代碼以下:
var olist = document.getElementById('olist'); olist.addEventListener('click',function(){ alert(event.target.innerText); },false);
看看實際運行的效果:
列表內容1
列表內容2
列表內容3
列表內容4
列表內容5
咱們並未給li元素綁定任何監聽器,而是監聽它的父元素ul,等到事件冒泡上來的時候,在處理函數中經過event.target得到觸發事件的li元素,進行相關處理。這樣作的好處是顯而易見的,首先只進行了一次監聽器的綁定,瀏覽器輕鬆,其次動態增長元素後你也沒必要要再綁定監聽器,你也輕鬆。正所謂你們好纔是真的好!
本篇的基本內容就介紹完了,你是否是感受有點奇妙,我平時寫程序的時候沒關心這些也仍然能完成工做呀?那我就得問你是否是使用js框架,使用jQuery了,事實上,jQuery提供的on、live等方法就已經對事件委託進行了封裝,爲委託機制的推廣悄悄作了底層貢獻,你沒感受到而已。jQuery中的各類事件監聽方式也須要咱們有一個清楚的瞭解,才能正確的使用,高效的完成工做。這些內容將放在下一篇介紹。