DOM事件類型之事件的傳播

前言

當(dāng)我們點(diǎn)擊一個(gè)事件例如onclick, 這個(gè)事件發(fā)生后使兔,會(huì)在子元素和父元素之間傳播(propagation)管闷,這個(gè)過程就叫做事件傳播显歧。

事件傳播的三個(gè)階段

  • 第一階段:從window對(duì)象傳導(dǎo)到目標(biāo)節(jié)點(diǎn)(上層傳到底層),稱為“捕獲階段”(capture phase)。
  • 第二階段:在目標(biāo)節(jié)點(diǎn)上觸發(fā)颊糜,稱為“目標(biāo)階段”(target phase)。
  • 第三階段:從目標(biāo)節(jié)點(diǎn)傳導(dǎo)回window對(duì)象(從底層傳回上層)秃踩,稱為“冒泡階段”(bubbling phase)衬鱼。
事件冒泡與事件捕獲

這種三階段的傳播模型,使得同一個(gè)事件會(huì)在多個(gè)節(jié)點(diǎn)上觸發(fā)憔杨。

xxx.addEventListener('click', callback, false);//冒泡  子傳父
xxx.addEventListener('click', callback, true);//捕獲 父?jìng)髯?

HMTL代碼片段:

<<!DOCTYPE html>
<html>
<head>
<script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
<meta charset="utf-8">
    <title>JS Bin</title>
</head>
<body>
<div class="red">
<div class="blue">
<div class="green">
  <div class="yellow">
    <div class="orange">
      <div class="purple">
      </div>
    </div>
  </div>
</div>
</div>
</div>
</body>
</html>

CSS代碼片段:

 *{margin:0;padding:0;box-sizing:border-box;}
  .red.active {
   background: red;
  }
.blue.active {
background: blue;
}
.green.active {
background: green;
}
.yellow.active {
background: yellow;
}
.orange.active {
background: orange;
}
.purple.active {
background: purple;
}
div {
  border: 1px solid black;
  padding: 10px;
  transition: all 0.5s;
  display: flex;
  flex:1;
  border-radius: 50%;
  background: white;
}

.red{
  width: 100vw;
  height: 100vw;
}

JS片段:

let divs = $('div').get()
let n = 0
for (let i = 0; i < divs.length; i++) {
  divs[i].addEventListener('click', () => {
    setTimeout(() => {
    divs[i].classList.add('active')
}, n * 500)
n += 1
}, false)
}


for (let i = 0; i < divs.length; i++) {
  divs[i].addEventListener('click', () => {
setTimeout(() => {
  divs[i].classList.remove('active')
}, n * 500)
n += 1
})
}

上面代碼中鸟赫,點(diǎn)擊子節(jié)點(diǎn)后父元素向子元素傳播,稱為捕獲階段消别,從子元素傳播到父元素抛蚤,稱為冒泡階段
具體效果:http://js.jirengu.com/zayipuvafo/1/edit?html,css,js,output
出現(xiàn)這種情況會(huì)對(duì)我們開發(fā)者并不友好寻狂,那么我會(huì)想辦法在我們想要的位置停止傳播岁经,那就用到事件代理

事件代理

由于事件會(huì)在冒泡階段向上傳播到父節(jié)點(diǎn),因此可以把子節(jié)點(diǎn)的監(jiān)聽函數(shù)定義在父節(jié)點(diǎn)上蛇券,由父節(jié)點(diǎn)的監(jiān)聽函數(shù)統(tǒng)一處理多個(gè)子元素的事件缀壤。這種方法叫做事件的代理(delegation)。

var ul = document.querySelector('ul');

ul.addEventListener('click', function (event) {
if (event.target.tagName.toLowerCase() === 'li') {
// some code
  }
});

上面代碼中纠亚,click事件的監(jiān)聽函數(shù)定義在<ul>節(jié)點(diǎn)塘慕,但是實(shí)際上,它處理的是子節(jié)點(diǎn)<li>的click事件蒂胞。這樣做的好處是图呢,只要定義一個(gè)監(jiān)聽函數(shù),就能處理多個(gè)子節(jié)點(diǎn)的事件骗随,而不用在每個(gè)<li>節(jié)點(diǎn)上定義監(jiān)聽函數(shù)岳瞭。而且以后再添加子節(jié)點(diǎn),監(jiān)聽函數(shù)依然有效蚊锹。

如果希望事件到某個(gè)節(jié)點(diǎn)為止瞳筏,不再傳播,可以使用事件對(duì)象的stopPropagation方法牡昆。

// 事件傳播到 p 元素后姚炕,就不再向下傳播了
p.addEventListener('click', function (event) {
event.stopPropagation();
}, true);

// 事件冒泡到 p 元素后摊欠,就不再向上冒泡了
p.addEventListener('click', function (event) {
 event.stopPropagation();
}, false);

上面代碼中,stopPropagation方法分別在捕獲階段和冒泡階段柱宦,阻止了事件的傳播些椒。

但是,stopPropagation方法只會(huì)阻止事件的傳播掸刊,不會(huì)阻止該事件觸發(fā)<p>節(jié)點(diǎn)的其他click事件的監(jiān)聽函數(shù)免糕。也就是說,不是徹底取消click事件忧侧。

 p.addEventListener('click', function (event) {
  event.stopPropagation();
  console.log(1);
});

p.addEventListener('click', function(event) {
// 會(huì)觸發(fā)
console.log(2);
});

上面代碼中石窑,p元素綁定了兩個(gè)click事件的監(jiān)聽函數(shù)。stopPropagation方法只能阻止這個(gè)事件向其他元素傳播蚓炬。因此松逊,第二個(gè)監(jiān)聽函數(shù)會(huì)觸發(fā)。輸出結(jié)果會(huì)先是1肯夏,然后是2经宏。

如果想要徹底阻止這個(gè)事件的傳播,不再觸發(fā)后面所有click的監(jiān)聽函數(shù)驯击,可以使用stopImmediatePropagation方法烁兰。

p.addEventListener('click', function (event) {
event.stopImmediatePropagation();
console.log(1);
});

p.addEventListener('click', function(event) {
// 不會(huì)被觸發(fā)
console.log(2);
});

上面代碼中,stopImmediatePropagation方法可以徹底阻止這個(gè)事件傳播徊都,使得后面綁定的所有click監(jiān)聽函數(shù)都不再觸發(fā)沪斟。所以,只會(huì)輸出1碟贾,不會(huì)輸出2币喧。

小結(jié):

事件傳播不可以避免,但是我們調(diào)用事件代理來得到我們想要的方案袱耽。自己也對(duì)dom事件模型有了更深的理解杀餐。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市朱巨,隨后出現(xiàn)的幾起案子史翘,更是在濱河造成了極大的恐慌,老刑警劉巖冀续,帶你破解...
    沈念sama閱讀 221,548評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件琼讽,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡洪唐,警方通過查閱死者的電腦和手機(jī)钻蹬,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來凭需,“玉大人问欠,你說我怎么就攤上這事肝匆。” “怎么了顺献?”我有些...
    開封第一講書人閱讀 167,990評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵旗国,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我注整,道長(zhǎng)能曾,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,618評(píng)論 1 296
  • 正文 為了忘掉前任肿轨,我火速辦了婚禮寿冕,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘萝招。我一直安慰自己蚂斤,他們只是感情好存捺,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,618評(píng)論 6 397
  • 文/花漫 我一把揭開白布槐沼。 她就那樣靜靜地躺著,像睡著了一般捌治。 火紅的嫁衣襯著肌膚如雪岗钩。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,246評(píng)論 1 308
  • 那天肖油,我揣著相機(jī)與錄音兼吓,去河邊找鬼。 笑死森枪,一個(gè)胖子當(dāng)著我的面吹牛视搏,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播县袱,決...
    沈念sama閱讀 40,819評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼浑娜,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了式散?” 一聲冷哼從身側(cè)響起筋遭,我...
    開封第一講書人閱讀 39,725評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎暴拄,沒想到半個(gè)月后漓滔,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,268評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡乖篷,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,356評(píng)論 3 340
  • 正文 我和宋清朗相戀三年响驴,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片撕蔼。...
    茶點(diǎn)故事閱讀 40,488評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡豁鲤,死狀恐怖石蔗,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情畅形,我是刑警寧澤养距,帶...
    沈念sama閱讀 36,181評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站日熬,受9級(jí)特大地震影響棍厌,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜竖席,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,862評(píng)論 3 333
  • 文/蒙蒙 一耘纱、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧毕荐,春花似錦束析、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,331評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至第美,卻和暖如春蝶锋,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背什往。 一陣腳步聲響...
    開封第一講書人閱讀 33,445評(píng)論 1 272
  • 我被黑心中介騙來泰國打工扳缕, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人别威。 一個(gè)月前我還...
    沈念sama閱讀 48,897評(píng)論 3 376
  • 正文 我出身青樓躯舔,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國和親省古。 傳聞我的和親對(duì)象是個(gè)殘疾皇子粥庄,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,500評(píng)論 2 359

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

  • ??JavaScript 與 HTML 之間的交互是通過事件實(shí)現(xiàn)的飒赃。 ??事件,就是文檔或?yàn)g覽器窗口中發(fā)生的一些特...
    霜天曉閱讀 3,500評(píng)論 1 11
  • Dom事件 事件是一種異步編程的實(shí)現(xiàn)方式科侈,本質(zhì)上是程序各個(gè)組成部分之間的通信载佳。DOM支持大量的事件 (一) Eve...
    woow_wu7閱讀 1,778評(píng)論 0 1
  • 事件是一種異步編程的實(shí)現(xiàn)方式,本質(zhì)上是程序各個(gè)組成部分之間的通信臀栈。DOM支持大量的事件蔫慧,本節(jié)介紹DOM的事件編程。...
    周花花啊閱讀 593評(píng)論 0 3
  • 事件是一種異步編程的實(shí)現(xiàn)方式权薯,本質(zhì)上是程序各個(gè)組成部分之間的通信姑躲。DOM支持大量的事件睡扬,本節(jié)介紹DOM的事件編程。...
    許先生__閱讀 948評(píng)論 0 3
  • 導(dǎo)讀:本文是teren對(duì)DOM事件知識(shí)點(diǎn)所做的進(jìn)一步整理黍析,整理資料主要參考DOM事件簡(jiǎn)介和饑人谷課件卖怜,如果對(duì)DOM...
    犯迷糊的小羊閱讀 4,027評(píng)論 1 5