javascript:深入理解事件流

事件流

定義
1.事件流描述的是從頁面中接收事件的順序,也可理解為事件在頁面中傳播的順序钟沛。
2.事件就是用戶或?yàn)g覽器自身執(zhí)行的某種動(dòng)作。諸如click(點(diǎn)擊)、load(加載)、mouseover(鼠標(biāo)懸停)择浊。
3.事件處理程序響應(yīng)某個(gè)事件的函數(shù)就叫事件處理程序(或事件偵聽器)檐蚜。

下面所示例子注冊(cè)事件的方式均使用DOM2級(jí)事件定義的事件處理程序進(jìn)行注冊(cè)充尉,兼容性的問題不涉及稠屠。'DOM2級(jí)事件'定義了兩個(gè)方法锤悄,用于處理指定和刪除事件處理程序的操作:addEventListener()removeEventListener()韧骗。所有DOM節(jié)點(diǎn)中都包含這兩個(gè)方法,并且它們都接收3個(gè)參數(shù):要處理的事件名零聚、作為事件處理程序的函數(shù)和一個(gè)布爾值袍暴。當(dāng)這個(gè)布爾值為true時(shí),表示在捕獲階段調(diào)用事件處理程序隶症;若果是false政模,表示在冒泡階段調(diào)用事件處理程序。

事件的作用范圍討論

示例1

html

  <div id="wrap">
    <div id="outer">
      <div id="inner"></div>
    </div>
  </div>

css

#wrap {
  width: 200px;
  height: 200px;
  background: orange;
}
#outer {
  position: relative;
  top: 50px;
  left: 50px;
  width: 100px;
  height: 100px;
  background: #eeddff;
}
#inner {
  position: relative;
  top: 25px;
  left:25px;
  width: 50px;
  height: 50px;
  background: #44ddff;
}

js

var wrap = document.getElementById('wrap');
wrap.addEventListener('click',function(){
  alert('789');
},false);

output

問題1:容器元素wrap注冊(cè)了事件蚂会,那么此事件的作用范圍是什么淋样?

思考1:根據(jù)上面例子,當(dāng)點(diǎn)擊橘色塊中(包括被子元素覆蓋的部分)任何一部分時(shí)胁住,都會(huì)彈出789趁猴,點(diǎn)擊橘色塊外面的部分并沒有任何反應(yīng),那么我們是不是就可以得出這這樣結(jié)論彪见,元素注冊(cè)事件的作用范圍為元素自身在頁面中所占的空間大小儡司,但是真的就是這樣嗎?下面我們做個(gè)試驗(yàn)

試驗(yàn)1:
css代碼修改如下,其他部分同上

#wrap {
  width: 200px;
  height: 200px;
  background: orange;
}
#outer {
  position: relative;
  top: 50px;
  left: 50px;
  width: 100px;
  height: 100px;
  background: #eeddff;
}
/*inner中的top被修改*/
#inner {
  position: relative;
  top: 152px;
  left:25px;
  width: 50px;
  height: 50px;
  background: #44ddff;
}

output

結(jié)論1:當(dāng)點(diǎn)擊橘色塊外淺藍(lán)色部分的時(shí)候,同樣的也彈出了789,而淺藍(lán)色部分是嵌套在wrap元素之內(nèi)的元素,故可得出結(jié)論,當(dāng)元素注冊(cè)了事件,此事件的作用范圍為:1.元素自己所占頁面空間部分加嵌套元素所占空間范圍(若嵌套元素覆蓋在容器元素上余指,則事件的作用范圍為容器元素自身所占空間大小)

事件的執(zhí)行順序討論

問題2:根據(jù)上面的示例1捕犬,那么這里大家可以再思考一個(gè)問題,若容器元素wrap以及其嵌套元素outer酵镜,inner都注冊(cè)了click事件碉碉,根據(jù)試驗(yàn)1得出的結(jié)論,那么嵌套在最里層的元素inner所占頁面的空間范圍內(nèi)淮韭,一共有3個(gè)click事件都作用在其上誉裆,那么當(dāng)在inner元素的作用范圍內(nèi)點(diǎn)擊頁面時(shí),3個(gè)事件的事件處理程序執(zhí)行的順序又是如何的缸濒?

要解決上面我提出的問題2,這就涉及到了兩種處理事件流的不同的機(jī)制足丢,事件冒泡和事件捕獲

事件冒泡###

IE的事件流叫事件冒泡粱腻,即事件開始時(shí)由最具體的元素(文檔中嵌套層次最深的節(jié)點(diǎn))接收,然后逐級(jí)向上傳播到較為不具體的節(jié)點(diǎn)斩跌。

示例2
將參數(shù)設(shè)為false绍些,讓元素在冒泡階段調(diào)用事件處理程序

css,html代碼同示例1
js

var wrap = document.getElementById('wrap');
var outer = document.getElementById('outer');
var inner = document.getElementById('inner');

wrap.addEventListener('click',function(){
  alert('789');
},false);
outer.addEventListener('click',function(){
  alert('456');
},false);
inner.addEventListener('click',function(){
  alert('123');
},false);

結(jié)論2:在冒泡階段調(diào)用事件處理程序,上面問題的結(jié)果是這樣的:當(dāng)點(diǎn)擊頁面中心淺藍(lán)色的部分時(shí)耀鸦,先是彈出123柬批,接著彈出456,最后彈出789袖订。因此當(dāng)容器元素及其嵌套元素都在冒泡階段調(diào)用事件處理程序時(shí):事件按事件冒泡的順序執(zhí)行事件處理程序氮帐。

事件捕獲###

Netscape團(tuán)隊(duì)提出的另一種事件流叫事件捕獲,事件捕獲的思想是不太具體的節(jié)點(diǎn)應(yīng)該更早接收到事件洛姑,而最具體的節(jié)點(diǎn)應(yīng)該最后接收到事件上沐。

示例3
將參數(shù)設(shè)為true,讓元素在捕獲階段調(diào)用事件處理程序

css,html代碼同示例1
js

var wrap = document.getElementById('wrap');
var outer = document.getElementById('outer');
var inner = document.getElementById('inner');
    
wrap.addEventListener('click',function(){
  alert('wrap');
},true);
outer.addEventListener('click',function(){
  alert('outer');
},true);
inner.addEventListener('click',function(){
  alert('inner');
},true);

結(jié)論3:在捕獲階段調(diào)用事件處理程序楞艾,上面問題的結(jié)果是這樣的:當(dāng)點(diǎn)擊頁面中心淺藍(lán)色的部分時(shí)参咙,先是彈出wrap,接著彈出outer硫眯,最后彈出inner蕴侧。因此當(dāng)容器元素及其嵌套元素都在捕獲階段調(diào)用事件處理程序時(shí):事件按事件捕獲的順序執(zhí)行事件處理程序。


問題3:根據(jù)思考1两入,思考2得出的結(jié)果净宵,接著又有一個(gè)問題我認(rèn)為需要思考,當(dāng)同一個(gè)元素即在冒泡階段注冊(cè)了事件裹纳,又在捕獲階段注冊(cè)了同一事件塘娶,那么當(dāng)事件被觸發(fā)時(shí),事件的執(zhí)行順序又會(huì)是如何的痊夭?

要解決上面我提出的問題3,這就涉及到了DOM事件流

DOM事件流###

DOM2級(jí)事件”規(guī)定的事件流包括三個(gè)階段:事件捕獲階段==>處于目標(biāo)階段==>事件冒泡階段。首先發(fā)生的是事件捕獲階段脏里,為截獲事件提供了機(jī)會(huì)她我。然后是實(shí)際的目標(biāo)接收事件。最后一個(gè)階段是冒泡階段迫横,以下圖片來自w3c

示例4
css,html代碼同示例1
js

var wrap = document.getElementById('wrap');
var outet = document.getElementById('outer');
var inner = document.getElementById('inner');

wrap.addEventListener('click',function(){
  alert('789');
},false);
outer.addEventListener('click',function(){
  alert('456');
},false);
inner.addEventListener('click',function(){
  alert('123');
},false);
wrap.addEventListener('click',function(){
  alert('wrap');
},true);
outer.addEventListener('click',function(){
  alert('outer');
},true);
inner.addEventListener('click',function(){
  alert('inner');
},true);

結(jié)論4:當(dāng)點(diǎn)擊頁面中心淺藍(lán)色部分的時(shí)候番舆,先從最不具體的節(jié)點(diǎn)捕獲事件,先彈出wrap,接著彈出outer矾踱。接著處于目標(biāo)階段恨狈,先彈出123,再彈出inner呛讲。緊接著禾怠,事件處于冒泡階段返奉,先彈出456,再彈出789吗氏。因此我們可以得出結(jié)論芽偏,當(dāng)容器元素及嵌套元素,即在捕獲階段又在冒泡階段調(diào)用事件處理程序時(shí):事件按DOM事件流的順序執(zhí)行事件處理程序弦讽,且當(dāng)事件處于目標(biāo)階段時(shí)污尉,事件調(diào)用順序決定于綁定事件的書寫順序,按上面的例子為往产,先調(diào)用冒泡階段的事件處理程序被碗,再調(diào)用捕獲階段的事件處理程序。
具體demo
如果把inner.addEventListener('click',function(){alert('inner');},true);
放到inner.addEventListener('click',function(){alert('123');},false);
前任意位置就會(huì)先執(zhí)行捕獲階段再執(zhí)行冒泡階段了仿村。所以處于目標(biāo)階段時(shí)锐朴,是先綁定的事件先發(fā)生。具體見這個(gè)demo---https://jsfiddle.net/levonlin/72tmu6vs/
[1]: /img/bVbDPh

“原文出自http://segmentfault.com/a/1190000003497939奠宜,
本文版權(quán)屬”huangxiulan(饑人谷)“所有包颁,轉(zhuǎn)載須注明出處”

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市压真,隨后出現(xiàn)的幾起案子娩嚼,更是在濱河造成了極大的恐慌,老刑警劉巖滴肿,帶你破解...
    沈念sama閱讀 222,681評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件岳悟,死亡現(xiàn)場離奇詭異,居然都是意外死亡泼差,警方通過查閱死者的電腦和手機(jī)贵少,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,205評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來堆缘,“玉大人滔灶,你說我怎么就攤上這事『鸱剩” “怎么了录平?”我有些...
    開封第一講書人閱讀 169,421評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長缀皱。 經(jīng)常有香客問我斗这,道長,這世上最難降的妖魔是什么啤斗? 我笑而不...
    開封第一講書人閱讀 60,114評(píng)論 1 300
  • 正文 為了忘掉前任表箭,我火速辦了婚禮,結(jié)果婚禮上钮莲,老公的妹妹穿的比我還像新娘免钻。我一直安慰自己彼水,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,116評(píng)論 6 398
  • 文/花漫 我一把揭開白布伯襟。 她就那樣靜靜地躺著猿涨,像睡著了一般。 火紅的嫁衣襯著肌膚如雪姆怪。 梳的紋絲不亂的頭發(fā)上叛赚,一...
    開封第一講書人閱讀 52,713評(píng)論 1 312
  • 那天,我揣著相機(jī)與錄音稽揭,去河邊找鬼俺附。 笑死,一個(gè)胖子當(dāng)著我的面吹牛溪掀,可吹牛的內(nèi)容都是我干的事镣。 我是一名探鬼主播,決...
    沈念sama閱讀 41,170評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼揪胃,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼璃哟!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起喊递,我...
    開封第一講書人閱讀 40,116評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤随闪,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后骚勘,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體铐伴,經(jīng)...
    沈念sama閱讀 46,651評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,714評(píng)論 3 342
  • 正文 我和宋清朗相戀三年俏讹,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了当宴。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,865評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡泽疆,死狀恐怖户矢,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情殉疼,我是刑警寧澤梯浪,帶...
    沈念sama閱讀 36,527評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站株依,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏延窜。R本人自食惡果不足惜恋腕,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,211評(píng)論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望逆瑞。 院中可真熱鬧荠藤,春花似錦伙单、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,699評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至淤井,卻和暖如春布疼,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背币狠。 一陣腳步聲響...
    開封第一講書人閱讀 33,814評(píng)論 1 274
  • 我被黑心中介騙來泰國打工游两, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人漩绵。 一個(gè)月前我還...
    沈念sama閱讀 49,299評(píng)論 3 379
  • 正文 我出身青樓贱案,卻偏偏與公主長得像,于是被迫代替她去往敵國和親止吐。 傳聞我的和親對(duì)象是個(gè)殘疾皇子宝踪,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,870評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容