You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.20 16:06:04