JavaScript中onClick事件错误选中元素问题求助
问题描述
点击任意骰子按钮时,都会选中第10个元素,尽管每个元素的id都已正确赋值。
代码实现
for(let x = 0; x < 10; x++){container_For_Dices.push(Math.round(Math.random()*10))} let Ids = ["Dice1","Dice2","Dice3","Dice4","Dice5","Dice6","Dice7","Dice8","Dice9","Dice10"] let id = -1 container_For_Dices= container_For_Dices.map((value=>{ id +=1 return( <button className="w-20 h-20 m-2 rounded-lg bg-slate-300 content-center pt-4 shadow shadow-gray-500 text-4xl font-bold dices" id={Ids[id]} onClick={()=>{ var element = document.getElementById(`${Ids[id]}`) element.classList.remove("dices") element.style.backgroundColor = "rgba(255,255,255,0.5)" }} > {value} </button> ) }))
解决方案
问题原因
这是典型的闭包陷阱:onClick中的箭头函数会捕获外部的id变量,当所有按钮渲染完成后,id已经被累加至9(对应第10个元素的索引),因此任何按钮被点击时,都会使用这个最终的id值去查找元素。
修复方法
方法1:利用map的索引参数 + 事件对象(推荐)
直接使用map自带的第二个参数(当前元素的索引),同时通过事件对象e.target获取点击的按钮元素,无需再通过id查找,代码更简洁且避免闭包问题:
for(let x = 0; x < 10; x++){container_For_Dices.push(Math.round(Math.random()*10))} const Ids = ["Dice1","Dice2","Dice3","Dice4","Dice5","Dice6","Dice7","Dice8","Dice9","Dice10"] container_For_Dices= container_For_Dices.map((value, index)=>{ return( <button className="w-20 h-20 m-2 rounded-lg bg-slate-300 content-center pt-4 shadow shadow-gray-500 text-4xl font-bold dices" id={Ids[index]} onClick={(e)=>{ const element = e.target element.classList.remove("dices") element.style.backgroundColor = "rgba(255,255,255,0.5)" }} > {value} </button> ) })
方法2:锁定当前迭代的id值
如果需要保留外部变量的写法,可以通过创建块级作用域锁定每个迭代的id值,确保点击事件捕获的是当前按钮对应的索引:
for(let x = 0; x < 10; x++){container_For_Dices.push(Math.round(Math.random()*10))} const Ids = ["Dice1","Dice2","Dice3","Dice4","Dice5","Dice6","Dice7","Dice8","Dice9","Dice10"] let id = -1 container_For_Dices= container_For_Dices.map((value=>{ id +=1 const currentId = id // 锁定当前迭代的id值 return( <button className="w-20 h-20 m-2 rounded-lg bg-slate-300 content-center pt-4 shadow shadow-gray-500 text-4xl font-bold dices" id={Ids[currentId]} onClick={()=>{ const element = document.getElementById(`${Ids[currentId]}`) element.classList.remove("dices") element.style.backgroundColor = "rgba(255,255,255,0.5)" }} > {value} </button> ) }))
内容的提问来源于stack exchange,提问作者Question
相关产品推荐
相关产品推荐

