從零開始學(xué)習(xí)javascript項(xiàng)目(2)——事件的監(jiān)聽谴古、捕獲和冒泡

從零開始學(xué)習(xí)javascript項(xiàng)目(2)

任務(wù)描述

  • 讀取頁面中id為source的列表切油,提取城市以及對(duì)應(yīng)的空氣質(zhì)量
  • 把數(shù)據(jù)排序以后,在resort列表中按照順序顯示出來
<ul id="source">
    <li>北京空氣質(zhì)量:<b>90</b></li>
    <li>上杭蛉恚空氣質(zhì)量:<b>70</b></li>
    <li>天津空氣質(zhì)量:<b>80</b></li>
    <li>廣州空氣質(zhì)量:<b>50</b></li>
    <li>深圳空氣質(zhì)量:<b>40</b></li>
    <li>福州空氣質(zhì)量:<b>32</b></li>
    <li>成都空氣質(zhì)量:<b>90</b></li>
  </ul>

  <ul id="resort">
    <!-- 
    <li>第一名:北京空氣質(zhì)量:<b>90</b></li>
    <li>第二名:北京空氣質(zhì)量:<b>90</b></li>
    <li>第三名:北京空氣質(zhì)量:<b>90</b></li>
     -->
  </ul>
  <button id="sort-btn">排序</button>

任務(wù)規(guī)劃

為了完成這個(gè)任務(wù),我們需要分成三個(gè)部分來完成這個(gè)動(dòng)作

  • 按下button的時(shí)候觸發(fā)動(dòng)作
  • 抓取頁面上的列表到一個(gè)數(shù)組里面
  • 把排序后的數(shù)組通過操作DOM使得新數(shù)組append到新的列表里面

綁定按鈕動(dòng)作與事件監(jiān)聽

和之前提到的一樣述暂,對(duì)于按鈕這個(gè)事件的觸發(fā)痹升,需要一個(gè)監(jiān)聽函數(shù)。首先使用抓取按鈕的DOM

var sort_btn = document.getElementById('sort-btn');

再對(duì)這個(gè)元素進(jìn)行監(jiān)聽動(dòng)作畦韭。

關(guān)于事件監(jiān)聽疼蛾,詳細(xì)點(diǎn)這里。如果不想看那么多艺配,可以看下面的精簡版察郁。

簡單的來說js的事件監(jiān)聽有三種方法

  • element.addEventListener(type, listener[, useCapture]); // IE6~8不支持
  • element.attachEvent(’on’ + type, listener); // IE6~10,IE11不支持
  • element[’on’ + type] = function(){} // 所有瀏覽器

舉個(gè)栗子:

function cb() { console.log(1); }
element.addEventListener('click', cb, false);
element.attachEvent('onclick', cb);
element.onclick = cb;

type :事件類型

listener :事件觸發(fā)后的回調(diào)函數(shù)

useCapture :是否使用捕獲转唉,如果值為true皮钠, useCapture 表示用戶希望發(fā)起捕獲。 在發(fā)起捕獲之后酝掩, 只要Dom子樹下發(fā)生了該事件類型鳞芙,都會(huì)先被該事件監(jiān)聽器捕獲,然后再被派發(fā)到Dom子樹中的事件監(jiān)聽器中期虾。并且向上冒泡的事件不會(huì)觸發(fā)那些發(fā)起捕獲的事件監(jiān)聽器原朝。 useCapture 默認(rèn)值為false

addEventListener是W3C工作組在DOM Level 2開始引入的一個(gè)注冊(cè)事件監(jiān)聽器的方法镶苞;而在此之前喳坠,傳統(tǒng)的事件監(jiān)聽方法是通過element[’on’ + type]的方式來注冊(cè)的。它們兩之間的主要區(qū)別是茂蚓,element[’on’ + type]的方式無法使用事件捕獲壕鹉,并且element[’on’ + type]不支持對(duì)同一個(gè)元素的同一個(gè)事件注冊(cè)多個(gè)事件監(jiān)聽器。如下面的例子所示聋涨,元素被點(diǎn)擊后只會(huì)輸出1晾浴,而不會(huì)輸出0和1.

element.onclick = function(){ console.log(0); }
element.onclick = function(){ console.log(1); }

看完我的解釋,是不是更加不明白了牍白?沒關(guān)系脊凰,趕緊點(diǎn)擊這里。 回過頭好好看一下好了茂腥。

淺談事件的捕獲和冒泡

對(duì)于所有中國人來說狸涌,有一個(gè)四字魔咒是永遠(yuǎn)繞不開的切省。只要有人對(duì)你說出這四個(gè)字,你就能中邪般地買票去最坑爹的景點(diǎn)帕胆、玩命爬上最艱險(xiǎn)的山峰朝捆、吃下最難吃的餐館飯菜…這四個(gè)字就是———來都來了。

所以懒豹,既然看到這了芙盘,我就帶你們?nèi)チ私庖稽c(diǎn)更深入的知識(shí)吧,畢竟來都來了 歼捐。

事件

javascript使用的是異步事件模型何陆,如果你寫過verilog,那么對(duì)這個(gè)概念應(yīng)該會(huì)比較熟悉豹储,而且javascript中的異步事件是基于觸發(fā)器的贷盲,也就是說你不必考慮異步時(shí)鐘域里面的數(shù)據(jù)傳輸而產(chǎn)生的亞穩(wěn)態(tài)和計(jì)算數(shù)據(jù)傳輸?shù)膸挕.惒绞录脑谟谥灰褂脮r(shí)間處理函數(shù)注冊(cè)一個(gè)回調(diào)函數(shù)剥扣,一旦事件觸發(fā)巩剖,就會(huì)立刻執(zhí)行回調(diào)函數(shù)。

DOM事件流的階段

所謂的事件流钠怯,就是事件在處理事件傳播過程中的順序佳魔,根據(jù)W3C模型的定義,這個(gè)傳播過程分別是捕獲階段晦炊,目標(biāo)階段鞠鲜,冒泡階段。事件階段存在的意義子啊與 當(dāng)我們?cè)谝粋€(gè)元素里面潛逃另外一個(gè)元素断国,并且這兩者都綁定了一個(gè)onClink事件贤姆,就像下面這樣

+-----------------+
|    event1       |
|  +-----------+  |
|  |  event2   |  |
|  +-----------+  |
|                 |
+-----------------+

(效果來自這里不是閑的蛋疼不要嘗試,不過畫點(diǎn)簡單的東西還是很給力的)稳衬。當(dāng)點(diǎn)擊事件發(fā)生的時(shí)候霞捡,哪一個(gè)先被觸發(fā),執(zhí)行的順序是什么薄疚?W3C模型采用的是一種先捕獲再冒泡的的方式碧信,大概就像下面這樣的。

                      / \\
+----------------| |--| |----------------+
| element1       | |  | |                |
|   +------------| |--| |----------+     |
|   |element2    \\ /  | |          |     |
|   +------------------------------+     |
|        W3C event model                 |
+----------------------------------------+

? 我們以一個(gè)例子來說明這種流程

<div id = "s1"> s1
  <div id = "s2">s2</div>
</div>
<script>
    s1.addEventListener("click",function(evt){
      console.log("s1捕獲模式");
    },true);
    s2.addEventListener("click",function(evt){
      console.log("s2捕獲模式");
    },true);
    s1.addEventListener("click",function(evt){
      console.log("s1冒泡模式");
    },false);
    s2.addEventListener("click",function(evt){
      console.log("s2冒泡模式");
    },false);
</script>    

結(jié)果如下

s1捕獲模式
s2捕獲模式
s2冒泡模式
s1冒泡模式

我們可以通過這個(gè)例子看到街夭,事件傳播的過程根據(jù)addEventListener方法設(shè)置的第三個(gè)參數(shù)確定捕獲的模式砰碴。在捕獲階段,事件到達(dá)事件目標(biāo)之前板丽,事件對(duì)象必須從windows經(jīng)過目標(biāo)的祖先節(jié)點(diǎn)傳播到時(shí)間目標(biāo)衣式,在這個(gè)階段注冊(cè)的事件監(jiān)聽器在到達(dá)目標(biāo)之前必須先處理事件。在目標(biāo)階段檐什,事件對(duì)象到達(dá)事件目標(biāo)碴卧,該階段的事件監(jiān)聽器就會(huì)對(duì)其進(jìn)行處理。最后就是冒泡階段乃正,事件對(duì)象以一個(gè)與捕獲階段相反的方向經(jīng)過祖節(jié)點(diǎn)傳播到window住册。在這個(gè)階段注冊(cè)的事件監(jiān)聽器會(huì)對(duì)相應(yīng)的冒泡時(shí)間進(jìn)行處理。

這樣就很清楚了瓮具。我再貼一張官方圖片:

事件觸發(fā)過程

如果你看不到上面的圖片荧飞,那么高清無碼大圖在這里 。當(dāng)然名党,我們也可以使用stopPropagation這個(gè)函數(shù)來停止事件的傳播叹阔,這里就不展開了。如果你有興趣的話传睹,可以研究一下關(guān)于IE對(duì)于事件捕獲的操作方法耳幢,通過監(jiān)聽父節(jié)點(diǎn)而不是監(jiān)聽父節(jié)點(diǎn)下面的每一個(gè)子節(jié)點(diǎn)來節(jié)約瀏覽器的資源,通過關(guān)閉冒泡和捕獲使函數(shù)的執(zhí)行互不干擾而節(jié)約瀏覽器的資源等等欧啤。

回歸主線

好了睛藻,說了這么多。我們?cè)谧约旱捻?xiàng)目里面需要用到的大概就是這么一句話

var sort_btn = document.getElementById('sort-btn');
sort_btn.addEventListener('click',function(){btnHandle()},false);

抓取列表元素到數(shù)組

這就是簡單的操作DOM的內(nèi)容了邢隧,我們的目標(biāo)是把城市和數(shù)字存到一個(gè)個(gè)的鍵值對(duì)中店印。

//函數(shù)應(yīng)該這么寫
function getData(){
  var data = document.getElementById('source').getElementByTagName('li');
  var a = [];
  var city;
  var num;
  for(var i=0; i<data.length; i++){
    city = data[i].innerHTML.substring(0,data[i].innerHTML.indexOf('空'));
    num = data[i].getElementByTagName('b')[0].innerHTML;
    a.push([city,num]);
  }
  return a;
}
  • innerHTML不僅可以修改HTML元素還可以把元素內(nèi)容返回出來。
  • substring用于提取字符串中介于兩個(gè)指定下標(biāo)之間的字符倒慧。其內(nèi)容是從 start 處到 stop-1 處的所有字符
  • indexOf() 方法可返回某個(gè)指定的字符串值在字符串中首次出現(xiàn)的位置

對(duì)列表元素進(jìn)行排序

這一部分也很簡單按摘,教科書一般的排序方式。

function sortAqiData(data){
    data.sort(function(a,b){
      return (a[1]-b[1]);
    }) 
}

通過操作DOM使排序后的數(shù)據(jù)顯示出來

function render(data){
    var resort = document.getElementById('resort');
    resort.innerHTML = '';
    for(var i=0; i< data.length; i++){
      var node = document.creatElement('li');
      var html = '第'+(i+1)+'名:'+data[i][0]+'空氣質(zhì)量:<b>'+data[i][1]+'</b>'纫谅;
      node.innerHTML = html;
      resort.appendChild(node);
    }
}

這樣炫贤,一個(gè)簡單的交互功能就算完成了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末系宜,一起剝皮案震驚了整個(gè)濱河市照激,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌盹牧,老刑警劉巖俩垃,帶你破解...
    沈念sama閱讀 218,607評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異汰寓,居然都是意外死亡口柳,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,239評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門有滑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來跃闹,“玉大人,你說我怎么就攤上這事⊥眨” “怎么了苛秕?”我有些...
    開封第一講書人閱讀 164,960評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長找默。 經(jīng)常有香客問我艇劫,道長,這世上最難降的妖魔是什么惩激? 我笑而不...
    開封第一講書人閱讀 58,750評(píng)論 1 294
  • 正文 為了忘掉前任店煞,我火速辦了婚禮,結(jié)果婚禮上风钻,老公的妹妹穿的比我還像新娘顷蟀。我一直安慰自己,他們只是感情好骡技,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,764評(píng)論 6 392
  • 文/花漫 我一把揭開白布鸣个。 她就那樣靜靜地躺著,像睡著了一般哮兰。 火紅的嫁衣襯著肌膚如雪毛萌。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,604評(píng)論 1 305
  • 那天喝滞,我揣著相機(jī)與錄音阁将,去河邊找鬼。 笑死右遭,一個(gè)胖子當(dāng)著我的面吹牛做盅,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播窘哈,決...
    沈念sama閱讀 40,347評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼吹榴,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了滚婉?” 一聲冷哼從身側(cè)響起图筹,我...
    開封第一講書人閱讀 39,253評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎让腹,沒想到半個(gè)月后远剩,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,702評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡骇窍,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,893評(píng)論 3 336
  • 正文 我和宋清朗相戀三年瓜晤,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片腹纳。...
    茶點(diǎn)故事閱讀 40,015評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡痢掠,死狀恐怖驱犹,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情足画,我是刑警寧澤雄驹,帶...
    沈念sama閱讀 35,734評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站锌云,受9級(jí)特大地震影響荠医,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜桑涎,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,352評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望兼贡。 院中可真熱鬧攻冷,春花似錦、人聲如沸遍希。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,934評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽凿蒜。三九已至禁谦,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間废封,已是汗流浹背州泊。 一陣腳步聲響...
    開封第一講書人閱讀 33,052評(píng)論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留漂洋,地道東北人遥皂。 一個(gè)月前我還...
    沈念sama閱讀 48,216評(píng)論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像刽漂,于是被迫代替她去往敵國和親演训。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,969評(píng)論 2 355

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

  • 以下文章為轉(zhuǎn)載贝咙,對(duì)理解JavaScript中的事件處理機(jī)制很有幫助样悟,淺顯易懂,特分享于此庭猩。 什么是事件窟她? 事件(E...
    jxyjxy閱讀 3,037評(píng)論 1 10
  • (續(xù)jQuery基礎(chǔ)(1)) 第5章 DOM節(jié)點(diǎn)的復(fù)制與替換 (1)DOM拷貝clone() 克隆節(jié)點(diǎn)是DOM的常...
    凜0_0閱讀 1,342評(píng)論 0 8
  • 事件是一種異步編程的實(shí)現(xiàn)方式,本質(zhì)上是程序各個(gè)組成部分之間的通信眯娱。DOM支持大量的事件礁苗,本節(jié)介紹DOM的事件編程。...
    周花花啊閱讀 593評(píng)論 0 3
  • 現(xiàn)在的孩子獨(dú)生子女居多徙缴,所以家長對(duì)孩子寵愛有加试伙。真象對(duì)待小皇帝一般嘁信。含在嘴里怕化了,捧在手里怕掉了疏叨。隨著時(shí)間的推移...
    光明自在行閱讀 569評(píng)論 2 6
  • 正常如你我的普通人蚤蔓,也許想的最多的就是怎么能多拿些工資卦溢;或者工作上的一堆破事讓自己牢騷滿腹,天天抱怨個(gè)沒完沒了...
    靜小酥閱讀 327評(píng)論 0 0