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

使用Handlebars填充jQuery手风琴时嵌套Div仅首行生效的问题

解决手风琴组件嵌套内容仅第一项生效的问题

这种动态生成的嵌套组件只在第一个项生效的坑我之前踩过好几次,大概率是选择器冲突、事件绑定方式不对,或者模板数据上下文错误导致的,给你几个针对性的排查和解决思路:

1. 立刻检查:是否用了重复的ID

ID在DOM里是唯一的,如果你的嵌套Div用了类似#nested-content这种固定ID,不管渲染多少个手风琴项,JS只会找到第一个匹配的元素。

解决办法:把嵌套容器的ID改成class,比如.nested-content,然后在Handlebars模板里统一使用class选择器:

{{#each accordionItems}}
<div class="accordion-item">
  <div class="accordion-header">{{title}}</div>
  <div class="accordion-body">
    <p>{{mainDetail}}</p>
    <!-- 用class代替ID -->
    <div class="nested-content">
      {{#each subItems}}
      <div class="nested-item">{{subTitle}}</div>
      {{/each}}
    </div>
  </div>
</div>
{{/each}}

2. 事件绑定要改用「事件委托」

如果你的手风琴展开事件是直接绑定在初始DOM元素上的(比如$('.accordion-header').click()),那动态生成的后续手风琴项不会触发这个事件,自然也不会加载嵌套内容。

解决办法:把事件绑定到父容器(或者document)上,通过事件委托处理动态元素:

// 错误写法:只绑定初始存在的元素
// $('.accordion-header').click(function() { ... })

// 正确写法:事件委托,覆盖所有动态生成的元素
$('.accordion-container').on('click', '.accordion-header', function() {
  // 基于当前点击的header,找到对应的body和嵌套容器
  const $targetBody = $(this).next('.accordion-body');
  const $nestedContent = $targetBody.find('.nested-content');
  
  // 切换展开/收起状态
  $targetBody.toggleClass('active');
  
  // 如果是动态加载嵌套数据,这里可以根据当前项的标识去请求数据
  // 比如 const itemId = $(this).data('item-id');
  // 然后把数据渲染到$nestedContent里
});

3. 确保模板数据是「项级独立」的

如果你的嵌套数据是全局的,没有和每个手风琴项绑定,那所有项的嵌套内容都会用同一份数据,甚至可能只有第一个项能正确渲染。

解决办法:保证每个手风琴项的数据源里包含自己的嵌套数据,比如:

const accordionData = {
  accordionItems: [
    {
      title: "手风琴项1",
      mainDetail: "主内容1",
      subItems: [{subTitle: "嵌套内容1-1"}, {subTitle: "嵌套内容1-2"}]
    },
    {
      title: "手风琴项2",
      mainDetail: "主内容2",
      subItems: [{subTitle: "嵌套内容2-1"}, {subTitle: "嵌套内容2-2"}]
    }
  ]
};

然后在Handlebars模板里通过{{#each subItems}}遍历当前项的嵌套数据,而不是全局的数组。

4. 定位元素时要基于「当前项上下文」

如果你的代码里是直接用$('.nested-content')来操作嵌套容器,那会选中所有匹配的元素,导致只有第一个被正确处理。

解决办法:永远从当前点击的手风琴header出发,向上/向下查找对应的嵌套容器,比如:

// 错误写法:操作所有嵌套容器
// $('.nested-content').html(xxx);

// 正确写法:只操作当前展开项的嵌套容器
$(this).next('.accordion-body').find('.nested-content').html(yourNestedTemplateData);

完整示例代码

给你一个能跑通的极简示例,你可以对照调整自己的代码:

Handlebars模板

<script id="accordion-tpl" type="text/x-handlebars-template">
  {{#each items}}
  <div class="accordion-item">
    <button class="accordion-header" data-item-id="{{id}}">{{title}}</button>
    <div class="accordion-body">
      <p>{{mainText}}</p>
      <div class="nested-box">
        {{#each nestedList}}
        <span class="nested-item">{{text}}</span>
        {{/each}}
      </div>
    </div>
  </div>
  {{/each}}
</script>

JS逻辑

// 1. 编译模板并渲染初始内容
const tpl = Handlebars.compile($('#accordion-tpl').html());
const data = {
  items: [
    {id: 1, title: "项1", mainText: "主内容1", nestedList: [{text: "嵌套1"}, {text: "嵌套2"}]},
    {id: 2, title: "项2", mainText: "主内容2", nestedList: [{text: "嵌套3"}, {text: "嵌套4"}]},
    {id: 3, title: "项3", mainText: "主内容3", nestedList: [{text: "嵌套5"}, {text: "嵌套6"}]}
  ]
};
$('.accordion-wrap').html(tpl(data));

// 2. 事件委托实现手风琴展开/收起
$('.accordion-wrap').on('click', '.accordion-header', function() {
  const $body = $(this).next('.accordion-body');
  $body.toggleClass('show');
});

基础CSS

.accordion-body {
  display: none;
  padding: 10px;
  border: 1px solid #eee;
}
.accordion-body.show {
  display: block;
}
.nested-box {
  margin-top: 10px;
  padding: 5px;
  background: #f5f5f5;
}

内容的提问来源于stack exchange,提问作者wcpulling

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 04:07:20