事件冒泡和事件捕獲分別由微軟和網景公司提出,這兩個概念都是爲了解決頁面中事件流(事件發生順序)的問題。html
<div id="outer">
<p id="inner">Click me!</p>
</div>複製代碼
上面的代碼當中一個div元素當中有一個p子元素,若是兩個元素都有一個click的處理函數,那麼咱們怎麼才能知道哪個函數會首先被觸發呢?node
爲了解決這個問題微軟和網景提出了兩種幾乎徹底相反的概念。web
微軟提出了名爲事件冒泡(event bubbling)的事件流。事件冒泡能夠形象地比喻爲把一顆石頭投入水中,泡泡會一直從水底冒出水面。也就是說,事件會從最內層的元素開始發生,一直向上傳播,直到document對象。瀏覽器
所以上面的例子在事件冒泡的概念下發生click事件的順序應該是bash
網景提出另外一種事件流名爲事件捕獲(event capturing)。與事件冒泡相反,事件會從最外層開始發生,直到最具體的元素。dom
上面的例子在事件捕獲的概念下發生click事件的順序應該是函數
事件冒泡和事件捕獲過程圖:性能
1-5是捕獲過程,5-6是目標階段,6-10是冒泡階段;
flex
DOM2級事件」中規定的事件流同時支持了事件捕獲階段和事件冒泡階段,而做爲開發者,咱們能夠選擇事件處理函數在哪個階段被調用。優化
addEventListener方法用來爲一個特定的元素綁定一個事件處理函數,是JavaScript中的經常使用方法。addEventListener有三個參數:
element.addEventListener(event, function, useCapture)複製代碼
參數 | 描述 |
---|---|
event
|
必須。字符串,指定事件名。 注意: 不要使用 "on" 前綴。 例如,使用 "click" ,而不是使用 "onclick"。 提示: 全部 HTML DOM 事件,能夠查看咱們完整的 HTML DOM Event 對象參考手冊。 |
function
|
必須。指定要事件觸發時執行的函數。 當事件對象會做爲第一個參數傳入函數。 事件對象的類型取決於特定的事件。例如, "click" 事件屬於 MouseEvent(鼠標事件) 對象。 |
useCapture
|
可選。布爾值,指定事件是否在捕獲或冒泡階段執行。 可能值:
|
在實際的開發當中,利用事件流的特性,咱們可使用一種叫作事件代理的方法。
<ul class="color_list">
<li>red</li>
<li>orange</li>
<li>yellow</li>
<li>green</li>
<li>blue</li>
<li>purple</li>
</ul>
<div class="box"></div>複製代碼
.color_list{
display: flex;
display: -webkit-flex;
}
.color_list li{
width: 100px;
height: 100px;
list-style: none;
text-align: center;
line-height: 100px;
}
//每一個li加上對應的顏色,此處省略
.box{
width: 600px;
height: 150px;
background-color: #cccccc;
line-height: 150px;
text-align: center;
}
複製代碼
咱們想要在點擊每一個 li 標籤時,輸出li當中的顏色(innerHTML)
。常規作法是遍歷每一個 li ,而後在每一個 li 上綁定一個點擊事件:
var color_list=document.querySelector(".color_list");
var colors=color_list.getElementsByTagName("li");
var box=document.querySelector(".box");
for(var n=0;n<colors.length;n++){
colors[n].addEventListener("click",function(){
console.log(this.innerHTML)
box.innerHTML="該顏色爲 "+this.innerHTML;
})
}複製代碼
這種作法在 li 較少的時候可使用,但若是有一萬個 li ,那就會致使性能下降(少了遍歷全部 li 節點的操做,性能上確定更加優化)。
這時就須要事件代理出場了,利用事件流的特性,咱們只綁定一個事件處理函數也能夠完成:
function colorChange(e){
var e=e||window.event;//兼容性的處理
if(e.target.nodeName.toLowerCase()==="li"){
box.innerHTML="該顏色爲 "+e.target.innerHTML;
}
}
color_list.addEventListener("click",colorChange,false)複製代碼
因爲事件冒泡機制,點擊了 li 後會冒泡到 ul ,此時就會觸發綁定在 ul 上的點擊事件,再利用 target 找到事件實際發生的元素,就能夠達到預期的效果。
使用事件代理的好處不只在於將多個事件處理函數減爲一個,並且對於不一樣的元素能夠有不一樣的處理方法。假如上述列表元素當中添加了其餘的元素節點(如:a、span等),咱們沒必要再一次循環給每個元素綁定事件,直接修改事件代理的事件處理函數便可。
(1)toLowerCase() 方法用於把字符串轉換爲小寫。語法:stringObject.toLowerCase()
返回值:一個新的字符串,在其中 stringObject 的全部大寫字符所有被轉換爲了小寫字符。
(2)nodeName 屬性指定節點的節點名稱。若是節點是元素節點,則 nodeName 屬性返回標籤名。若是節點是屬性節點,則 nodeName 屬性返回屬性的名稱。對於其餘節點類型,nodeName 屬性返回不一樣節點類型的不一樣名稱。
全部主流瀏覽器均支持 nodeName 屬性。
對於事件代理來講,在事件捕獲或者事件冒泡階段處理並無明顯的優劣之分,可是因爲事件冒泡的事件流模型被全部主流的瀏覽器兼容,從兼容性角度來講仍是建議你們使用事件冒泡模型。
IE瀏覽器對addEventListener兼容性並不算太好,只有IE9以上可使用。
要兼容舊版本的IE瀏覽器,可使用IE的attachEvent函數
object.attachEvent(event, function)
兩個參數與addEventListener類似,分別是事件和處理函數,默認是事件冒泡階段調用處理函數,要注意的是,寫事件名時候要加上"on"前綴("onload"、"onclick"等)。
1. 給子級加 event.stopPropagation( )
$("#div1").mousedown(function(e){
var e=event||window.event;
event.stopPropagation();
});複製代碼
2. 在事件處理函數中返回 false
$("#div1").mousedown(function(event){
var e=e||window.event;
return false;
});複製代碼
可是這兩種方式是有區別的。return false
不只阻止了事件往上冒泡,並且阻止了事件自己(默認事件)。event.stopPropagation()
則只阻止事件往上冒泡,不阻止事件自己。
3. event.target==event.currentTarget,讓觸發事件的元素等於綁定事件的元素,也能夠阻止事件冒泡;
(2)return false
感謝您的閱讀,有不足之處請爲我指出!