冒泡,捕獲,委託,事件的所有祕密一覽無餘

本篇文章參考以下博文
https://www.jianshu.com/p/d3e9b653fa95

事件冒泡

我們先象徵性的舉個例子,幫助大家有一個具像的理解,下面有三個盒子,他們嵌套在一起。

<div id="num1" onClick={console.log(1)}>

  <div id="num2" onClick='console.log(2)'>
  
    <div id="num3" onClick='console.log(3)'></div>
    
  </div>
  
</div>

當點擊黃色盒子的時候,控制檯輸出的結果爲3,2,1。
在這裏插入圖片描述雖然點擊的是黃色盒子,但是瀏覽器不管你點的是誰,只關心你點的位置有幾個元素,點擊黃色區域,有三個元素,所以三個元素都被判定爲點擊,這個類似於你打了別人肚子一拳,雖然是打在他的衣服上面了,但是人家可不管那個,就判定你打他了。

事件冒泡的輸出順序比較好理解,點擊的誰,就從誰開始,一層一層往外擴散,直到擴散到document,還是上面的例子,當你打別人的時候,力量是先傳遞到衣服上,然後再傳遞到被打人的肉上,一層一層傳遞。

事件捕獲

事件捕獲正好和冒泡相反,修改一下代碼

<div id="num1">
    <div id="num2">
      <div id="num3"></div>
    </div>
  </div>
  <script>
  
    let div1 = document.getElementById('num1');
    div1.addEventListener('click', function () {
      console.log(1)
    }, true)
    
    let div2 = document.getElementById('num2');
    div2.addEventListener('click', function () {
      console.log(2)
    }, true)
    
    let div3 = document.getElementById('num3');
    div3.addEventListener('click', function () {
      console.log(3)
    }, true)
    
  </script>

上面添加監聽事件的方式是爲了修改事件捕獲,當addEventListener的第三個參數爲true的時候,爲事件捕獲,默認爲false,這次我們還是點擊黃色區域,輸出結果如下:
在這裏插入圖片描述
這次順序完全反了過來,可以理解爲,程序在執行過程中,要從上往下執行代碼,執行到最外層(粉色)div的時候,發現他有一個點擊事件,鼠標點擊的位置還正好在他的範圍之內,那就先把他執行了,別的以後再說。

這樣一層一層往裏執行,找到誰就執行誰,所以執行順序爲1,2,3。

事件委託

事件委託的機制源於冒泡,現在有一個<ul>,裏面有1000個<li>需要添加監聽事件,這個時候就不能一個一個的給<li>添加監聽事件了,累死也加不完。

這時候就需要用到剛學習過的事件冒泡了,我們已經知道點擊一個<li>的時候,事件會冒泡到<ul>上,那直接給<ul>添加上點擊事件就可以了,不管點到哪個<li>上都能觸發。

當然了,我們還是要區分到底是點擊的哪個<li>的,比如這個例子,<ul>裏面有1000個<li>,當我點擊其中一個<li>的時候,希望它高亮顯示。我們可以用以下方法實現

let ul = document.getElementById('ul');
  ul.addEventListener('click', function (e) {
  
    let id = e.target.getAttribute('id') //獲取元素的id屬性
    
    let li = document.getElementById(id); //這裏id沒有加引號,是在使用上面剛剛獲取到的id屬性
    
    li.classList.add("className1") //添加class屬性,可以在className1中寫上高亮樣式
    
  }, false)

阻止事件冒泡和捕獲

有時候我們不想冒泡,點誰就誰執行,別人別搗亂

let ul = document.getElementById('ul');
  ul.addEventListener('click', function (e) {
  
    ...
    
    e.stopPropagation() //加上這個就可以阻止冒泡了,同樣也適用於捕獲
  })

上面提到了e.target,這個東西能幫我們獲取到是誰觸發的點擊事件,但當使用一些第三方庫的組件的時候,e.target可能無法獲取到我們想要的元素,這個時候需要使用e.currentTarget,具體詳情請查看以下博文

e.target與e.currentTarget多一個current到底經歷了什麼?

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章