You need to enable JavaScript to run this app. 点击Handlebars动态生成的按钮仅获取首个元素的问题求助
优惠活动
大模型
产品
解决方案
定价
更多

点击Handlebars动态生成的按钮仅获取首个元素的问题求助

问题原因

  • HTML 规范要求 id 属性全局唯一,你在 Handlebars 循环渲染时给多组商品元素重复设置了相同的 id="name"、id="price"、id="id",原生 document.getElementById() 方法只会返回 DOM 树中第一个匹配到的元素,因此每次都只能拿到第一条商品的数据。
  • placeOrder 方法没有和当前点击的按钮绑定对应商品数据,无法识别用户点击的是哪个商品的按钮。

修复方案

方案1:直接传参(最简单快捷)

1. 修改 Handlebars 模板

移除重复的 ID,换成 class,调用方法时直接把当前循环的商品数据作为参数传入:

<script type="text/x-handlebars-template" id="demo">
   {{#each this}}
      <h2 class="name">{{stock_name}}</h2>
      <h2 class="id" style="display: none;">{{stock_id}}</h2>
      <h4 class="price">{{stock_price}}</h4>
      <button class="btn" onclick="placeOrder('{{stock_name}}', '{{stock_price}}', '{{stock_id}}')">加入购物车</button>
   {{/each}}
</script>

2. 修改 placeOrder.js 方法

直接接收传入的参数,不需要再查询 DOM 取值:

function placeOrder(stockName, stockPrice, stockId){
    console.log(stockName);
    console.log(stockPrice);
    
    var table = document.getElementById("cartItem");
    var row = table.insertRow(1);
    var nameCell = row.insertCell(0);
    var countCell = row.insertCell(1);
    var priceCell = row.insertCell(2);
    var idCell = row.insertCell(3);
    nameCell.innerHTML = stockName;
    priceCell.innerHTML = stockPrice;
    countCell.innerHTML = 1;
    idCell.innerHTML = stockId;
}

方案2:事件委托(最佳实践,避免内联事件)

如果不想在模板里写内联点击事件,可以用事件委托的方式实现,后续维护更方便:

1. 修改 Handlebars 模板

给每组商品套一个外层容器,移除内联点击事件:

<script type="text/x-handlebars-template" id="demo">
   {{#each this}}
   <div class="goods-item">
      <h2 class="name">{{stock_name}}</h2>
      <h2 class="id" style="display: none;">{{stock_id}}</h2>
      <h4 class="price">{{stock_price}}</h4>
      <button class="btn">加入购物车</button>
   </div>
   {{/each}}
</script>

2. 新增事件绑定逻辑

在 Handle.js 的 createHTML 方法末尾新增事件委托绑定,或者单独放在 placeOrder.js 中:

// 给容器绑定点击事件,统一处理所有商品按钮的点击
document.getElementById('container').addEventListener('click', function(e) {
    // 仅处理点击按钮的场景
    if (!e.target.classList.contains('btn')) return
    // 找到当前按钮所属的商品容器
    const currentGoods = e.target.closest('.goods-item')
    const stockName = currentGoods.querySelector('.name').textContent
    const stockPrice = currentGoods.querySelector('.price').textContent
    const stockId = currentGoods.querySelector('.id').textContent
    // 调用下单逻辑
    placeOrder(stockName, stockPrice, stockId)
})

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

相关产品推荐
方舟 Agent Plan

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

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