JavaScript 網頁事件處理 2


Posted by tzutzu858 on 2020-08-07

新手 100% 會搞錯的事件機制問題

先做兩個按鈕

<div class="outer">
    <button class="btn">1</button>
    <button class="btn">2</button>
  </div>

  <script>
      document.querySelector(".btn")
        .addEventListener('click', function () {
          alert(1)
        })
  </script>

結果只按一個,另一個沒反應是正常的,因為 document.querySelector 只會回傳第一個元素,想要幫每一個都加就要用 document.querySelectorAll,但 document.querySelectorAll 回傳的是一個 list ,他雖然不是陣列,但可以當作陣列來用

 const elements = document.querySelectorAll(".btn")
    for (var i = 0; i < elements.length; i++) {
      elements[i].addEventListener('click', function () {
        alert(i)
      })
    }

但發現不管按哪個按鈕都是 2 ,問題在於 function 並不是在加的那一刻出發,而是在點擊的那一刻出發,點擊的那一刻,i 的值已經變成 elements.length
要怎麼改變呢? 用 e.target 來拿到到底點了什麼東西

 const elements = document.querySelectorAll(".btn")
    for (var i = 0; i < elements.length; i++) {
      elements[i].addEventListener('click', function (e) {
        console.log(e.target)
      })
    }

e.target.getAttribute("data-value") 就可以拿到 data-value 這個屬性就 OK 了

.setAttribute()
設置指定元素上的某個屬性值。如果屬性已經存在,則更新該值;否則,使用指定的名稱和值添加一個新的屬性。
語法 :

element.setAttribute(name, value);

如果要新增一個按鈕,按下去會再新增按紐
先新增一個按鈕 <button class="add-btn">add</button>

document.querySelector(".add-btn").addEventListener("click",
      function () {
        const btn = document.createElement("button")
        btn.setAttribute("data-value", num)
        btn.innerText = num
        num++
        document.querySelector(".outer").appendChild(btn)
      })

但是新增的按鈕沒有 EventListener ,而且如果有一百個按鈕是否要新增一百個按鈕,這很沒有效率尤其他們性質又很相似,所以其實我們可以在最上層冒泡新增 EventListener ,那下面所有包含動態產生的都可以監聽到,這就叫做 event delegation 。

<body>
  <div class="outer">
    <button class="add-btn">add</button>
    <button class="btn" data-value="1">1</button>
    <button class="btn" data-value="2">2</button>

  </div>

  <script>
    let num = 3
    const elements = document.querySelectorAll(".btn")
    for (var i = 0; i < elements.length; i++) {
      elements[i].addEventListener('click', function (e) {
        alert(e.target.getAttribute("data-value"))
      })
    }

    document.querySelector(".add-btn").addEventListener("click",
      function () {
        const btn = document.createElement("button")
        btn.setAttribute("data-value", num)
        btn.classList.add("btn")
        btn.innerText = num
        num++
        document.querySelector(".outer").appendChild(btn)
      }
    )

    document.querySelector(".outer").addEventListener("click",
      function (e) {
        if (e.target.classList.contains("btn")) {
          alert(e.target.getAttribute("data-value"))
        }
      }
    )

  </script>
</body>

  • 使用 classList 屬性是取得元素 Class 的一種便利方式,也可以透過 element.className 來得到以空格分隔之 Class 清單字串。

  • HTML5 中的 data-* attribute 屬性










Related Posts

使用者行為分析&RFM分析

使用者行為分析&RFM分析

[ 學習筆記系列 ] 後端基礎 (全) - MySQL 語法、基礎 PHP 與 Session / Cookie

[ 學習筆記系列 ] 後端基礎 (全) - MySQL 語法、基礎 PHP 與 Session / Cookie

JavaScript 核心 - 來講講提升(hoisting)

JavaScript 核心 - 來講講提升(hoisting)


Comments