JavaScript中querySelectorAll绑定的点击事件仅对首个元素生效问题
问题:点击任意first-card卡片仅首个触发翻转效果
我正在自学JavaScript,制作一款记忆类桌游。页面存在多个class为first-card的卡片,为其绑定点击事件后,点击任意卡片仅首个卡片会触发翻转效果。相关代码如下:
JavaScript代码
document.querySelectorAll(".first-card").forEach(container => { container.addEventListener('click', flipCard) }) function flipCard() { document.querySelector(".first-card").classList.toggle("flip") }
CSS代码
*, *::before, *::after { box-sizing: border-box; } body { padding: 100px; display: flex; } .first-card, .second-card { width: 100px; height: 150px; border: 3px solid black; border-radius: 10px; transition: 0.6s; transform-style: preserve-3d; position: relative; margin: 10px; } .flip { transform: rotateY(180deg); } .front, .back { backface-visibility: hidden; position: absolute; top: 0; left: 0; } .front { z-index: 2; transform: rotateY(0deg); } .back { transform: rotateY(180deg); } .first-card .front { background: lightblue; width: 100%; height: 100%; } .second-card .front { background: red; width: 100%; height: 100%; } .first-card .back, .second-card .back { background: black; width: 100%; height: 100%; }
HTML代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <link rel="stylesheet" type="text/CSS" href="memory.css" /> </head> <body> <div class="first-card"> <div class="front"> front </div> <div class="back"> back </div> </div> <div class="second-card"> <div class="front"> front </div> <div class="back"> back </div> </div> <div class="first-card"> <div class="front"> front </div> <div class="back"> back </div> </div> <div class="second-card"> <div class="front"> front </div> <div class="back"> back </div> </div> <script src="memory.js"></script> </body> </html>
问题原因
flipCard函数里的document.querySelector(".first-card")是核心问题——querySelector方法仅会返回匹配选择器的第一个DOM元素。无论你点击哪个卡片,每次触发事件时都会找到页面上第一个class为first-card的元素,给它切换flip类,所以只有第一个卡片会有翻转效果。
我们实际需要操作的是当前被点击的那个卡片元素,而不是固定的第一个元素。
解决方法
修改flipCard函数,将固定选择元素的代码替换为指向当前点击元素的引用:
方法1:使用this关键字
事件触发时,this会指向绑定该事件的DOM元素(也就是被点击的卡片):
document.querySelectorAll(".first-card").forEach(container => { container.addEventListener('click', flipCard) }) function flipCard() { this.classList.toggle("flip") }
方法2:使用事件对象的currentTarget属性
事件对象的currentTarget属性同样指向绑定事件的元素(比target更可靠,避免事件冒泡影响):
document.querySelectorAll(".first-card").forEach(container => { container.addEventListener('click', flipCard) }) function flipCard(event) { event.currentTarget.classList.toggle("flip") }
扩展优化
如果希望second-card也能触发点击翻转效果,只需修改选择器,同时绑定两类卡片的点击事件:
document.querySelectorAll(".first-card, .second-card").forEach(container => { container.addEventListener('click', flipCard) }) function flipCard() { this.classList.toggle("flip") }
内容的提问来源于stack exchange,提问作者Andrej_CRO
相关产品推荐
相关产品推荐

