API返回动态内容时addEventListener绑定无效、手风琴联动及map调用报错问题
问题根因
1. 所有手风琴同时开合
点击事件触发后你遍历了全部.panel元素统一修改显示状态,没有匹配当前点击按钮对应的专属面板,所以点击一个就会控制所有面板同步变化。
另外你把事件绑定逻辑写在了创建元素的i循环内部,每新增一组手风琴就给所有已存在的按钮重复绑定多次事件,进一步导致逻辑混乱。
2. 追加递增序号后事件失效
你使用innerHTML +=的方式追加元素,该操作会先清空#sidebar内已有的所有DOM元素,再把拼接后的整体内容重新渲染为新DOM,之前给旧元素绑定的事件监听器会随旧DOM销毁全部丢失,新加序号的元素是重建后的新元素,没有绑定事件自然无法触发。
3. "map is not a function"报错
document.querySelectorAll返回的是NodeList类数组对象,不是标准JS数组,低版本浏览器中NodeList原型未挂载map方法,直接调用就会抛出该错误。如果需要使用数组方法,可先通过Array.from(document.querySelectorAll('选择器'))将其转为标准数组后再操作。
修复后的完整代码
HTML 代码
<style type="text/css"> #sidebar p { display: none; } .accordion.active { /* 可自定义激活状态的按钮样式 */ background: #e0e0e0; } </style> <div id="sidebar"></div>
JS 代码
window.onload = function(){ let xhr = null; if (window.XMLHttpRequest || window.ActiveXObject) { if (window.ActiveXObject) { try { xhr = new ActiveXObject("Msxml2.XMLHTTP"); // 兼容IE } catch(exception) { xhr = new ActiveXObject("Microsoft.XMLHTTP"); // 兼容IE } } else { xhr = new XMLHttpRequest(); } } else { alert("Your browser does not support XMLHTTP Request...!"); return; } xhr.open("GET", "https://jsonplaceholder.typicode.com/users", true); xhr.send(null); xhr.onreadystatechange = function(){ if (xhr.readyState == 4 && xhr.status == 200) { const data = JSON.parse(xhr.responseText); const sidebar = document.querySelector("#sidebar"); // 先拼接所有HTML内容,一次性写入DOM,避免多次重绘销毁事件 let htmlStr = ''; data.forEach(item => { htmlStr += `<button class='accordion'>${item.name}</button>`; htmlStr += `<p class='panel'>${item.email} ${item.address.city} ${item.company.name}</p><br/>`; }) sidebar.innerHTML = htmlStr; // 统一绑定事件,只绑定一次 const accordions = document.querySelectorAll(".accordion"); accordions.forEach(btn => { btn.addEventListener('click', function () { this.classList.toggle("active"); // 直接取当前按钮的下一个相邻元素,就是对应的panel,不用遍历所有 const currentPanel = this.nextElementSibling; currentPanel.style.display = currentPanel.style.display === "block" ? "none" : "block"; }) }) } } }
内容的提问来源于stack exchange,提问作者Rashmi UI
相关产品推荐
相关产品推荐

