2013-08-07 109 views
4

我試圖理解JavaScript的addEventListener()中的useCapture參數。這裏是我的HTML:addEventListener中的useCapture表現奇怪

<div id="wrapper"> 
    <button id="button">Click me</button> 
</div> 

這裏是我的JavaScript:

document.getElementById('wrapper').addEventListener('click', function() { console.log('Wrapper capture'); }, true); 
document.getElementById('wrapper').addEventListener('click', function() { console.log('Wrapper bubble'); }, false); 
document.getElementById('button').addEventListener('click', function() { console.log('Button bubble'); }, false); 
document.getElementById('button').addEventListener('click', function() { console.log('Button capture'); }, true); 

現在,我預計爲了Wrapper capture, Button capture, Button bubble, Button bubble。出人意料的是,這裏是我的輸出:

Wrapper capture 
Button bubble 
Button capture 
Wrapper bubble 

兩個按鈕處理程序混錯?我在其他瀏覽器中測試過它,但Chrome,Firefox和IE10都顯示相同的行爲。我對此感到有點困惑。 The MDN,QuirksMode.orgthe spec都清楚地描述了不同階段以及捕獲階段如何在冒泡階段之前。 Button bubble處理程序在我的Button capture之前如何調用我的小實驗?

這裏是發生了什麼事情的小提琴:http://jsfiddle.net/Tr7G6/2


//更新 看來附加的處理關係的順序。

document.getElementById('wrapper').addEventListener('click', function() { console.log('Wrapper capture'); }, true); 
document.getElementById('wrapper').addEventListener('click', function() { console.log('Wrapper bubble'); }, false); 
document.getElementById('button').addEventListener('click', function() { console.log('Button capture'); }, true); 
document.getElementById('button').addEventListener('click', function() { console.log('Button bubble'); }, false); 

綁定捕獲第一和泡沫第二確實產生我期望的,跨瀏覽器的輸出。但這很愚蠢。爲什麼這個命令很重要?

回答

1

冒泡/捕獲僅在事件觸發/捕獲到目標元素時才起作用,而不是直接在該元素上觸發事件(這是W3C事件模型的「目標階段」)。在沒有「泡泡」或「捕捉」的情況下 - <button>上的click事件就是這種情況 - 事件按添加的順序進行處理。

例如,如果你到顛倒您的「包裝」聽衆的順序,然後點擊包裝元素(不是按鈕),你會發現相同的行爲(泡沫將火在前):

// 1. "Wrapper Bubble" 2. "Wrapper Capture" 
document.getElementById('wrapper').addEventListener('click', function() { console.log('Wrapper bubble'); }, false); 
document.getElementById('wrapper').addEventListener('click', function() { console.log('Wrapper capture'); }, true); 

但是,如果您要使用相同的順序(捕捉前的氣泡)並單擊button,捕捉將在氣泡之前觸發。這是因爲「點擊」事件正在button上觸發,並在「冒泡」(正常事件流)之前通過dom被「捕獲」。

我已經創建了一個JSBIN,希望有助於澄清這一點(但是,它可能會增加混淆)。 「有序」按鈕/ div觸發您的第一個片段的順序,而「無序」按鈕和div使用第二個順序。

欲瞭解更多信息,請參閱this SO答案和W3C Event Flow文檔,特別是Target Phase

+1

好奇的是,他們只是忽略了任何優先順序,只是因爲「它總是在同一個元素上」。我無法在規範中找到文本文本,但是在給出您的解釋以及在此行爲之後的跨瀏覽器實現後,它必須是真實的!謝謝 :) –