新手 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 清單字串。