JS实现购物车商品添加时始终返回数组最后一项问题求助
问题原因
- 核心是全局变量作用域+行内事件触发时机的问题:
- 你在函数外声明了全局变量
let necklace,for循环中每次迭代都会给这个全局变量重新赋值,整个循环执行完成后,necklace的值固定为necklaces数组的最后一个元素 - 行内
onclick事件的代码是点击时才会在全局作用域下执行,你拼接的onclick='add(necklace)'里的necklace指向的是全局变量,所以不管点击哪个按钮,取到的都是循环结束后最终的necklace值,也就是最后一个商品
- 你在函数外声明了全局变量
- 额外潜在问题:你给div写的
<div ${necklaces[index].name}>缺少属性名,属于无效属性,不会报错但也没有实际作用
解决方法
有两种常用修复方案,选任意一种即可:
方案1:拼接事件时直接传入当前迭代的数组下标,避免依赖全局变量
修改showNecklaces函数代码如下:
function showNecklaces() { display.innerHTML = ""; for (let index = 0; index < necklaces.length; index++) { // 不需要再依赖全局necklace变量,直接把下标写死到onclick参数里 display.innerHTML += `<div> ${necklaces[index].name} , ${necklaces[index].price} , <img src="${necklaces[index].img}"></div> <button class="btn btn-primary" onclick='add(necklaces[${index}])'> Add to cart</button> `; } }
拼接完成后每个按钮的onclick代码会变成add(necklaces[0])、add(necklaces[1])这种固定指向对应下标的代码,点击时就会取到正确的商品。
方案2:放弃行内onclick,改用事件绑定(更推荐,避免全局作用域污染)
这种方案不用拼接事件代码,而是渲染完元素后给每个按钮绑定事件,绑定的时候就把对应商品传进去:
function showNecklaces() { display.innerHTML = ""; for (let index = 0; index < necklaces.length; index++) { // 循环内部用const声明变量,每次迭代都是独立作用域 const necklace = necklaces[index]; // 创建商品容器 const goodsDiv = document.createElement('div'); goodsDiv.innerHTML = ` ${necklace.name} , ${necklace.price} , <img src="${necklace.img}"> <button class="btn btn-primary"> Add to cart</button> `; // 给按钮绑定点击事件,直接引用当前循环的necklace变量 goodsDiv.querySelector('.btn-primary').addEventListener('click', () => add(necklace)); display.appendChild(goodsDiv); } }
内容的提问来源于stack exchange,提问作者AYB
相关产品推荐
相关产品推荐

