for循环/btns/adiv

本文探讨了在JavaScript中利用事件循环为多个按钮添加点击事件,通过改变按钮样式及关联div元素宽度的方法。作者详细记录了解决过程中的常见错误与最终正确实践,包括如何正确引用当前点击按钮的序号来定位并修改对应的div元素。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

当在一个for循环中,给每个btns加事件,在事件中,当前选中的btns会改变样式,其他不变,同时对应序号的div也会改变宽度(或高幅度其他样式)。
实现过程中,因为是给btns加事件,所以只要使用this.className就可以改变,但是对应序号的div无法选中。
①做出几下几种改变:

 for(var i =0 ; i<ali.length ; i++){        
       ali[i].onclick = function(){
            for(var i = 0; i <ali.length; i++){
                ali[i].className = ' ';
        }
            this.className = 'active';
            adiv[i].style.width = 200+'px';
        }
    }
    会提示报错:

Cannot read property ‘style’ of undefined
at HTMLLIElement.ali.(anonymous function).onclick

for(var i =0 ; i <ali.length ; i++){
           ali[i].onclick = function(){
                var temp = i;  //在每个点击事件中获取当前的i序号
                for(var i = 0; i <ali.length; i++){
                    ali[i].className = '';
            }
                this.className = 'active';
                adiv[temp].style.width = 200+'px';
            }
        }

 会提示相同错误提示

卧槽!!!!!!!终于对啦,跟老师鞠躬道歉是自己没有认真看老师的写法导自己浪费了人生在找错误。

        for(var i =0 ; i <ali.length ; i++){
        ali[i].index = i; //在每个点击按钮上上添加属性index,且第i个的index对应是i
         ali[i].onclick = function(){ 
            for(var i = 0; i <ali.length; i++){
            ali[i].className = '';
        }
            this.className = 'active';
            adiv[this.index].style.width = 200+'px';  //在div选择对应序号的时候,使用this.index可以快速找到对应序号的div
        }

    }
这是我的shoppingcar.js文件:// 页面加载完成后执行a函数 window.onload = a; // a函数,页面加载完成后执行的函数 function a() { // 获取所有全选复选框 var selectall = document.querySelectorAll(".selectAll"); // 获取所有单选复选框 var checkbox = document.querySelectorAll("[name=check]"); // 为每个全选复选框添加点击事件监听器 selectall.forEach(sa => sa.onclick = e => { // 遍历所有全选复选框,将它们的状态设置为点击的复选框的状态 selectall.forEach(sa => sa.checked = e.target.checked); // 遍历所有单选复选框,将它们的状态设置为点击的复选框的状态 checkbox.forEach(cb => cb.checked = e.target.checked); // 调用total函数计算总价 total(); }); // 为每个单选复选框添加点击事件监听器 checkbox.forEach(cb => cb.onclick = checkAll); // 获取所有数量输入框 var number = document.querySelectorAll("[type=number]"); // 为每个数量输入框添加改变事件监听器 number.forEach(nb => nb.onchange = e => { // 获取价格和数量 var price = e.target.parentNode.parentNode.querySelector(".price").innerText; var number = e.target.value; // 计算小计并设置到页面上 e.target.parentNode.parentNode.querySelector(".subtotal").innerText = Number(price * number).toFixed(2); // 调用total函数计算总价 total(); }); // 加载商品数据 load(); // 为每个删除按钮添加点击事件监听器 document.querySelectorAll(".del").forEach(de => { de.onclick = () => { // 获取父元素 var parent = de.parentNode.parentNode.parentNode; // 获取父元素的父元素 var parent1 = de.parentNode.parentNode; // 确认是否删除 if (confirm("确认删除")) { // 移除父元素 parent.removeChild(parent1); } // 调用total函数计算总价 total(); }; }); // 为删除选中商品按钮添加点击事件监听器 document.querySelector("#delcheck").onclick = () => { // 获取选中的商品数量 var a = confirm("删除选中的商品"); // 遍历所有单选复选框 document.querySelectorAll("input[name=check]").forEach(de => { // 如果复选框被选中且确认删除,则移除父元素 if (de.checked && a) { var parent = de.parentNode.parentNode.parentNode; var parent1 = de.parentNode.parentNode; if (confirm("确认删除?")) { parent.removeChild(parent1); } } }); }; // 调用total函数计算总价 total(); } // 检查所有复选框是否都被选中 function checkAll() { // 获取所有全选复选框 var selectall = document.querySelectorAll(".selectAll"); // 获取所有单选复选框 var checkbox = document.querySelectorAll("[name=check]"); // 获取单选复选框的总数 var total = checkbox.length; // 获取选中的单选复选框的数量 var count = 0; // 遍历单选复选框 checkbox.forEach(cb => { // 如果复选框被选中,计数器加1 if (cb.checked) count++; }); // 如果所有单选复选框都被选中,将全选复选框也设置为选中状态 if (count === total) { selectall.forEach(sa => sa.checked = true); } else { // 否则 selectall.forEach(sa => sa.checked = false); } } // 计算总价 function total() { // 获取所有商品项 var items = document.querySelectorAll(".item"); // 初始化总价 var sum = 0; // 遍历商品项 for (var item of items) { // 如果单选复选框被选中 if (item.querySelector("[name=check]").checked) { // 累加小计到总价 sum += Number(item.querySelector(".subtotal").innerText); } } // 设置总价到页面上 document.querySelector("#totalprice").innerText = sum.toFixed(2); } // 异步加载商品数据 function load() { // 使用fetch API异步获取JSON数据 fetch("./js/products.json").then(resp => resp.json()).then(res => { // 输出商品数据到控制台 console.log(res); // 如果数据加载成功 if (res.status === "success") { // 输出商品数据到控制台 console.log(res.data); // 获取商品列表容器 const dom = document.querySelector(".productsBox"); // 初始化HTML字符串 let html = ""; // 遍历商品数据 for (const p of res.data) { // 构建商品HTML并添加到容器 html += `<div class="product"> <img src="img/${p.img}" height="100"> <p>${p.name}</p> <div>¥${p.price}</div> <button>加入购物车</button> </div>`; } // 将HTML设置为商品列表容器的innerHTML dom.innerHTML = html; // 获取所有按钮 const btns = dom.querySelectorAll("button"); // 为每个按钮添加点击事件监听器 btns.forEach((b, index) => { b.onclick = () => { // 添加商品到购物车 addToCart(res.data[index]); }; }); } }).catch(e => { // 处理错误 console.error("加载失败,请重试"); }); } // 添加商品到购物车 function addToCart(product) { // 获取所有商品项 const items = document.querySelectorAll(".item"); // 遍历商品项 for (const item of items) { // 如果商品名称与当前商品相同 if (item.querySelector("div:nth-child(3)").innerHTML.trim() === product.name) { // 获取数量输入框 const number = item.querySelector("[type=number]"); // 增加数量 number.value = Number(number.value) + 1; // 触发改变事件 number.dispatchEvent(new Event("change")); // 返回,避免继续添加相同的商品 return; } } // 构建新的商品HTML并添加到购物车列表 let html = ` <div class="item"> <div><input type="checkbox" name="check" /></div> <div><img src="img/${product.img}" height="100" /></div> <div>${product.name}</div> <div>¥<span class="price">${product.price}</span></div> <div><input type="number" value="1" min="1" /></div> <div>¥<span class="subtotal">${product.price}</span></div> <div><a href="#" class="del">删除</a></div> </div>`; // 将HTML添加到购物车列表 document.querySelector("#listBox").innerHTML += html; // 重新绑定事件监听器 a(); } ,这是我的index.html:<!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>京东商城 - 购物车</title> <link href="css/font-awesome.min.css" rel="stylesheet" /> <link href="css/style.css" rel="stylesheet" /> </head> <body> <header></header> <div class="content"> <div class="t-head"><h4>全部商品</h4></div> <div class="sct"> <div class="thead"> <div><input type="checkbox" class="selectAll" /></div> <div>全选</div> <div>商品</div> <div>单价</div> <div>数量</div> <div>小计</div> <div>操作</div> </div> <div id="listBox"> <div class="item"> <div><input type="checkbox" name="check" /></div> <div><img src="img/product5.jpg" height="100" /></div> <div>光明 纯牛奶250mL*24盒</div> <div>¥<span class="price">58.80</span></div> <div><input type="number" value="1" min="1" /></div> <div>¥<span class="subtotal">58.80</span></div> <div><a href="#" class="del">删除</a></div> </div> <div class="item"> <div><input type="checkbox" name="check" /></div> <div><img src="img/product5.jpg" height="100" /></div> <div>光明 纯牛奶250mL*24盒</div> <div>¥<span class="price">58.80</span></div> <div><input type="number" value="1" min="1" /></div> <div>¥<span class="subtotal">58.80</span></div> <div><a href="#" class="del">删除</a></div> </div> <div class="item"> <div><input type="checkbox" name="check" /></div> <div><img src="img/product5.jpg" height="100" /></div> <div>光明 纯牛奶250mL*24盒</div> <div>¥<span class="price">58.80</span></div> <div><input type="number" value="1" min="1" /></div> <div>¥<span class="subtotal">58.80</span></div> <div><a href="#" class="del">删除</a></div> </div> <div class="item"> <div><input type="checkbox" name="check"></div> <div><img src="img/product1.jpg" height="100"></div> <div>新品华为笔记本MateBook D 14/15 轻薄本商务办公本笔记本电脑学生 D15i5-10210U 16 512G独显灰</div> <div>¥<span class="price">5239.00</span></div> <div><input type="number" value="1" min="1"></div> <div>¥<span class="subtotal">5239.00</span></div> <div><a href="#" class="del">删除</a></div> </div> </div> <div class="countBox"> <div><input type="checkbox" class="selectAll" /></div> <div>全选 <a href="#" id="delcheck">删除选中的商品</a></div> <div> <span class="gray">总价:</span> ¥<span id="totalprice">0.00</span> </div> <div>去结算</div> </div> </div> </div> <div class="p-head"><h5>猜你喜欢</h5></div> <div class="productsBox"> <div class="product"> <img src="img/product1.jpg" height="100" /> <p> 新品华为笔记本MateBook D 14/15 轻薄本商务办公本笔记本电脑学生 D15 i5-10210U 16 512G独显灰 </p> <div>¥5239.00</div> <button class="add-to-cart"> <i class="fa fa-shopping-cart" aria-hidden="true"></i> 加入购物车 </button> </div> <div class="product"> <img src="img/product1.jpg" height="100" /> <p> 新品华为笔记本MateBook D 14/15 轻薄本商务办公本笔记本电脑学生 D15 i5-10210U 16 512G独显灰 </p> <div>¥5239.00</div> <button> <i class="fa fa-shopping-cart" aria-hidden="true"></i> 加入购物车 </button> </div> </div> <footer></footer> <script src="js/shoppingcar.js"></script> </body> </html>,这是我的productsjson{ "status": "success", "data": [ { "name": "新品华为笔记本MateBook D 14/15 轻薄本商务办公本笔记本电脑学生 D15i5-10210U 16 512G独显灰", "img": "product1.jpg", "price": "5239.00" }, { "name": "新款Huawei/华为折叠手机mates xs5g版大屏双屏全面屏双面屏官方旗舰店对折手机可折叠屏 Mate XS折叠", "img": "product2.jpg", "price": "20980.00" }, { "name": "华为智慧屏V55i-A 55英寸 HEGE-550 4K超薄全面屏液晶电视机 多方视频通话AI升降摄像头 4GB+64GB 星际黑", "img": "product3.jpg", "price": "3999.00" }, { "name": "华为荣耀智能手表WATCH Magic运动男女2Pro手环定位NFC支付陶瓷版(流沙杏)", "img": "product4.jpg", "price": "699.00" } ] } ,请详细注释shoppingcar.js中每行代码的意思
最新发布
06-23
<think>我们有一个购物车功能的JavaScript文件(shoppingcar.js),需要逐行注释其功能。同时,我们还有index.html和products.json的片段,但主要关注shoppingcar.js。注意:由于代码较长,我们将逐行解释,但会合并相似的部分。开始注释:</think>以下是对 `shoppingcar.js` 文件的逐行详细注释: ```javascript // 页面加载完成后执行a函数 window.onload = a; // a函数:页面初始化主逻辑 function a() { // 获取所有全选复选框元素 var selectall = document.querySelectorAll(".selectAll"); // 获取所有商品项的单选复选框 var checkbox = document.querySelectorAll("[name=check]"); // 为每个全选复选框绑定点击事件 selectall.forEach(sa => sa.onclick = e => { // 将所有全选复选框状态同步为当前点击状态 selectall.forEach(sa => sa.checked = e.target.checked); // 将所有商品复选框状态同步为当前点击状态 checkbox.forEach(cb => cb.checked = e.target.checked); // 重新计算总价 total(); }); // 为每个商品复选框绑定点击事件 checkbox.forEach(cb => cb.onclick = checkAll); // 获取所有数量输入框 var number = document.querySelectorAll("[type=number]"); // 为每个数量输入框绑定change事件 number.forEach(nb => nb.onchange = e => { // 获取当前商品行的价格元素 var price = e.target.parentNode.parentNode.querySelector(".price").innerText; // 获取修改后的数量 var number = e.target.value; // 计算小计并更新DOM e.target.parentNode.parentNode.querySelector(".subtotal").innerText = Number(price * number).toFixed(2); // 重新计算总价 total(); }); // 加载商品数据 load(); // 为每个删除按钮绑定点击事件 document.querySelectorAll(".del").forEach(de => { de.onclick = () => { // 获取商品项和其父容器 var parent = de.parentNode.parentNode.parentNode; var parent1 = de.parentNode.parentNode; if (confirm("确认删除")) { // 从DOM中移除商品项 parent.removeChild(parent1); } // 重新计算总价 total(); }; }); // 为"删除选中商品"按钮绑定点击事件 document.querySelector("#delcheck").onclick = () => { // 二次确认删除 var a = confirm("删除选中的商品"); // 遍历所有商品复选框 document.querySelectorAll("input[name=check]").forEach(de => { if (de.checked && a) { var parent = de.parentNode.parentNode.parentNode; var parent1 = de.parentNode.parentNode; if (confirm("确认删除?")) { parent.removeChild(parent1); } } }); // 删除后重新计算总价 total(); }; // 初始化总价计算 total(); } // 检查全选状态 function checkAll() { // 获取全选复选框和商品复选框 var selectall = document.querySelectorAll(".selectAll"); var checkbox = document.querySelectorAll("[name=check]"); var total = checkbox.length; // 商品总数 var count = 0; // 已选商品计数 // 统计已选商品数量 checkbox.forEach(cb => { if (cb.checked) count++; }); // 根据选择状态更新全选复选框 if (count === total) { selectall.forEach(sa => sa.checked = true); } else { selectall.forEach(sa => sa.checked = false); } // 重新计算总价 total(); } // 计算总价函数 function total() { // 获取所有商品项 var items = document.querySelectorAll(".item"); var sum = 0; // 总价累加器 // 遍历每个商品项 for (var item of items) { // 只计算选中的商品 if (item.querySelector("[name=check]").checked) { // 累加小计金额 sum += Number(item.querySelector(".subtotal").innerText); } } // 更新总价显示 document.querySelector("#totalprice").innerText = sum.toFixed(2); } // 加载商品数据 function load() { // 从JSON文件获取数据 fetch("./js/products.json") .then(resp => resp.json()) .then(res => { console.log(res); if (res.status === "success") { console.log(res.data); const dom = document.querySelector(".productsBox"); // 商品展示容器 let html = ""; // HTML内容缓冲区 // 动态生成商品列表 for (const p of res.data) { html += `<div class="product"> <img src="img/${p.img}" height="100"> <p>${p.name}</p> <div>¥${p.price}</div> <button>加入购物车</button> </div>`; } dom.innerHTML = html; // 为每个"加入购物车"按钮绑定事件 const btns = dom.querySelectorAll("button"); btns.forEach((b, index) => { b.onclick = () => { // 将对应商品加入购物车 addToCart(res.data[index]); }; }); } }) .catch(e => { console.error("加载失败,请重试"); }); } // 添加商品到购物车 function addToCart(product) { // 检查是否已存在相同商品 const items = document.querySelectorAll(".item"); for (const item of items) { // 通过商品名称比对 if (item.querySelector("div:nth-child(3)").innerHTML.trim() === product.name) { const number = item.querySelector("[type=number]"); // 增加已有商品数量 number.value = Number(number.value) + 1; // 触发change事件更新小计 number.dispatchEvent(new Event("change")); return; // 结束函数 } } // 新建商品项HTML let html = ` <div class="item"> <div><input type="checkbox" name="check" /></div> <div><img src="img/${product.img}" height="100" /></div> <div>${product.name}</div> <div>¥<span class="price">${product.price}</span></div> <div><input type="number" value="1" min="1" /></div> <div>¥<span class="subtotal">${product.price}</span></div> <div><a href="#" class="del">删除</a></div> </div>`; // 插入新商品项 document.querySelector("#listBox").innerHTML += html; // 重新初始化事件监听器 a(); } ``` ### 关键功能说明: 1. **初始化流程** - `window.onload` 触发主函数 `a()` 初始化购物车 - 绑定全选/单选事件、数量修改事件、删除事件 - 加载商品数据并渲染"猜你喜欢"区域 2. **核心交互** - **全选联动**:点击全选按钮同步所有商品选中状态 - **动态计价**:修改数量时实时计算小计和总价 - **商品去重**:添加已有商品时自动增加数量 - **批量删除**:支持删除选中商品 3. **数据流** - 通过 `fetch` 加载 `products.json` 商品数据 - 动态生成商品展示区并绑定添加事件 - 购物车数据存储在 DOM 中(无后端交互) 4. **DOM操作** - 使用 `querySelectorAll` 批量操作元素 - 事件委托:通过父元素查目标节点(如 `parentNode.parentNode`) - 动态创建商品项时使用字符串拼接 HTML ### 潜在优化建议: 1. 使用事件委托替代遍历绑定(提高性能) 2. 添加商品时避免重建整个事件系统(改用事件委托) 3. 价格计算使用 `Number()` 转换避免字符串拼接错误 4. 删除商品时添加动画效果增强用户体验
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值