为JS新创建的按钮绑定事件监听器时仅初始按钮可触发如何解决?
问题根因
- 每次执行
loadPerson函数时,都会覆盖divElem的innerHTML,旧的按钮元素会被销毁,新生成的按钮没有绑定过点击事件,无法触发交互。 - 获取按钮元素的代码仅在脚本初始化时执行一次,后续生成的新按钮不会被重新获取,事件无法绑定到新元素上。
- 额外注意:原有代码中
window.addEventListener("DOMContentLoaded", loadPerson(0))写法错误,你直接执行了loadPerson(0),把返回值传给了监听函数,正确写法应该是传入函数引用() => loadPerson(0)。 - 原有向前按钮逻辑存在漏洞:当前是第一条评论时,点击向前跳转的逻辑会实际跳转到倒数第二条,后续方案中也做了修正。
解决方案
方案1:事件委托(推荐)
将事件绑定到不会被销毁的父容器上,通过事件冒泡匹配触发事件的目标元素,不需要反复绑定解绑事件,性能更优。
修改后的完整JS代码如下:
const ourReview = document.getElementById("ourReview"); let count = 0; const divElem = document.createElement("div"); function loadPerson(personNum, arr = reviews) { divElem.className = "review-modal"; divElem.innerHTML = ` <img src="${arr[personNum].img}" alt="${arr[personNum].name}"/> <h2>${arr[personNum].name}</h2> <span>${arr[personNum].job}</span> <p>${arr[personNum].text}</p> <div id="arrow-button"> <button id="frd-btn"><</button> <button id="bck-btn">></button> </div> <button id="suprise">Suprise me</button> </div>`; ourReview.parentNode.append(divElem); } // 父容器绑定事件,做事件委托 divElem.addEventListener("click", (e) => { const targetId = e.target.id; if(targetId === "frd-btn") { count--; if (count < 0) { count = reviews.length - 1; } loadPerson(count); } else if(targetId === "bck-btn") { count++; if (count > reviews.length - 1) { count = 0; } loadPerson(count); } else if(targetId === "suprise") { const randomNum = Math.floor(Math.random()*reviews.length) loadPerson(randomNum); } }) window.addEventListener("DOMContentLoaded", () => loadPerson(0));
方案2:每次渲染后重新绑定事件
将获取按钮、绑定事件的逻辑封装为独立函数,每次渲染完评论内容后调用该函数,给新生成的按钮绑定事件。
修改后的核心代码如下:
const ourReview = document.getElementById("ourReview"); let count = 0; const divElem = document.createElement("div"); // 封装绑定事件的函数 function bindBtnEvents() { let frdBtn = document.getElementById("frd-btn"); let bckBtn = document.getElementById("bck-btn"); let suprise = document.getElementById("suprise"); frdBtn.addEventListener("click", () => { count--; if (count < 0) { count = reviews.length - 1; } loadPerson(count); }); bckBtn.addEventListener("click", () => { count++; if (count > reviews.length - 1) { count = 0; } loadPerson(count); }); suprise.addEventListener("click",() => { const randomNum = Math.floor(Math.random()*reviews.length) loadPerson(randomNum); }) } function loadPerson(personNum, arr = reviews) { divElem.className = "review-modal"; divElem.innerHTML = ` <img src="${arr[personNum].img}" alt="${arr[personNum].name}"/> <h2>${arr[personNum].name}</h2> <span>${arr[personNum].job}</span> <p>${arr[personNum].text}</p> <div id="arrow-button"> <button id="frd-btn"><</button> <button id="bck-btn">></button> </div> <button id="suprise">Suprise me</button> </div>`; ourReview.parentNode.append(divElem); // 渲染完成后调用绑定事件函数 bindBtnEvents(); } window.addEventListener("DOMContentLoaded", () => loadPerson(0));
内容的提问来源于stack exchange,提问作者Arihant
相关产品推荐
相关产品推荐

