点击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
相关产品推荐
相关产品推荐

