以前写购物车,总是或多或少会留下几个小bug被学生捉虫,这次把以前jQuery写的一个商城项目的购物车单独拎出来,用原生js(ES6)再写一次,希望是零漏洞了。
点击图片看效果。
功能:很多很多小细节,就不罗列了,直接上代码。
/* 1、点击加减按钮,临界值判断,数量变化,复选框勾上,全选判断,商品价格变化,总商品数量,总价格,结算按钮变化 2、输入数量,临界值判断,数据合法性判断、复选框勾上,商品价格变化,全选判断,总商品数量,总价格,结算按钮变化 3、点击复选框,商品总价,总数量,结算按钮变化,影响全选 4、点击全选,单个复选框,商品总价,总数量,结算按钮变化 5、点击删除按钮,全选框,全选框的可用性,商品总价,总数量,结算按钮变化 6、删除选中的商品,全选框,全选框的可用性,商品总价,总数量,结算按钮变化 */ { const max = 5; const min = 1; // 找对象 const oTrs = $All('tbody tr'); const oTotalPrice = $('.fy-cart-totalPrice'); const oTotalNum = $('.fy-cart-checked-totalNum'); const oBtnSubmit = $('.fy-cart-btnSubmit'); const oCheckAlls = $All('.fy-cart-checkAll'); const oBtnDelAll = $('#fy-cat-delAll'); oTrs.forEach(function (item) { cart(item); }) function cart(oTr) { const oBtnAdd = oTr.querySelector('.fy-pro-num-add'); const oBtnJian = oTr.querySelector('.fy-pro-num-minus'); const oNum = oTr.querySelector('.fy-pro-num-total'); const oSinglePrice = oTr.querySelector('.fy-cart-nowSinglePrice'); const oPrice = oTr.querySelector('.fy-cart-nowTotalPrice'); const oSingleCheck = oTr.querySelector('.singleCheck'); const oBtnDel = oTr.querySelector('.fy-del-book'); // 点击加号 // 临界值判断,数量变化,复选框勾上,商品价格变化 , 总商品数量,总价格,结算按钮变化 oBtnAdd.addEventListener('click', function () { let num = oNum.value; // 数量变化 num++; // 临界值判断 if (num >= max) { this.disabled = true; } if (oBtnJian.disabled) { oBtnJian.disabled = false; } oNum.value = num; // 复选框勾上 oSingleCheck.checked = true; // 商品价格变化 oPrice.innerHTML = '¥' + (oSinglePrice.innerHTML.slice(1) * num).toFixed(2); // 总价格总商品数量 getTotalNumAndPrice(); // 结算按钮变化 isBtnSubmitEnabled(); // 判断全选 isCheckAll(); }) oBtnJian.addEventListener('click', function () { let num = oNum.value; // 数量变化 num--; // 临界值判断 if (num <= min) { this.disabled = true; } if (oBtnAdd.disabled) { oBtnAdd.disabled = false; } oNum.value = num; // 复选框勾上 oSingleCheck.checked = true; // 商品价格变化 oPrice.innerHTML = '¥' + (oSinglePrice.innerHTML.slice(1) * num).toFixed(2); // 总价格总商品数量 getTotalNumAndPrice(); // 结算按钮变化 isBtnSubmitEnabled(); // 判断全选 isCheckAll(); }) // 2、输入数量,临界值判断,复选框勾上,商品价格变化,总商品数量,总价格,结算按钮变化 oNum.addEventListener('keydown', function (e) { let key = e.key; console.log(key); // 键盘只能输入数字1-9或者取消 if (!(key >= 1 && key <= 9 || key === 'Backspace')) { e.preventDefault(); } }) // 数量输入框临界值判断 oNum.addEventListener('input', function (e) { let val = this.value; console.log(val); if (val <= 1) { val = 1; oBtnJian.disabled = true; if (oBtnAdd.disabled) { oBtnAdd.disabled = false; } } else if (val >= max) { val = max; oBtnAdd.disabled = true; if (oBtnJian.disabled) { oBtnJian.disabled = false; } } else { oBtnAdd.disabled = false; oBtnJian.disabled = false; } this.value = val; // 复选框勾上 oSingleCheck.checked = true; // 商品价格变化 oPrice.innerHTML = '¥' + (oSinglePrice.innerHTML.slice(1) * val).toFixed(2); // 总价格总商品数量 getTotalNumAndPrice(); // 结算按钮变化 isBtnSubmitEnabled(); // 判断全选 isCheckAll(); }) // 3、点击复选框,商品总价,总数量,结算按钮变化,影响全选 oSingleCheck.addEventListener('change', function () { // 总价格总商品数量 getTotalNumAndPrice(); // 结算按钮变化 isBtnSubmitEnabled(); // 判断全选 isCheckAll(); }) // 5、点击删除按钮,全选框,商品总价,总数量,结算按钮变化 oBtnDel.addEventListener('click', function () { let parent = this.closest('tr'); parent.remove(); // 判断全选 isCheckAll(); // 全选框可用性判断 let oSingleChecks = $All('.singleCheck'); if (oSingleChecks.length == 0) { oCheckAlls.forEach(function (item) { item.disabled = true; item.checked = false; }) } // 总价格总商品数量 getTotalNumAndPrice(); // 结算按钮变化 isBtnSubmitEnabled(); }) } // 4、点击全选,单个复选框,商品总价,总数量,结算按钮变化 oCheckAlls.forEach(function (item) { item.addEventListener('change', function () { console.log(this); // 把全选的状态给两个全选框 // 回调函数内部的this默认指向window对象,可以通过传参,把 this绑定在某个具体的对象上。 oCheckAlls.forEach(function (item) { item.checked = this.checked; }, this); // 把全选的状态给每一个单个的复选康 let oSingleChecks = $All('.singleCheck'); oSingleChecks.forEach(function (item) { item.checked = this.checked; console.log(this); }, this) // 总价格总商品数量 getTotalNumAndPrice(); // 结算按钮变化 isBtnSubmitEnabled(); }) }) // 6、删除选中的商品,全选框,商品总价,总数量,结算按钮变化 oBtnDelAll.addEventListener('click', function (e) { let oCheckedInputs = document.querySelectorAll('.singleCheck:checked'); if (!oCheckedInputs.length) { alert('需要先选择一个商品'); return; } let result = confirm('你确定要删除吗?'); // console.log(result); if (result) { oCheckedInputs.forEach(function (item) { item.closest('tr').remove(); }) } else { e.preventDefault(); } // 全选框可用性判断 let oSingleChecks = $All('.singleCheck'); if (oSingleChecks.length == 0) { oCheckAlls.forEach(function (item) { item.disabled = true; item.checked = false; }) } // 总价格总商品数量 getTotalNumAndPrice(); // 结算按钮变化 isBtnSubmitEnabled(); }) // 计算总的数量和价格 function getTotalNumAndPrice() { // 找到所有被选中的复选框,把里面所有的总价累加求和。 let oCheckedInputs = document.querySelectorAll('.singleCheck:checked'); // console.log(oCheckedInputs) // 保存每个被选中的复选框对应的商品的总价格。 let priceArr = []; let numArr = []; oCheckedInputs.forEach(function (item) { let parent = item.closest('tr'); // console.log(parent); let price = +(parent.querySelector('.fy-cart-nowTotalPrice').innerHTML).slice(1); let num = +(parent.querySelector('.fy-pro-num-total').value); priceArr.push(price); numArr.push(num); }) // 把数组里面每个商品的总价进行累加求和,就是所有被选中的商品的总价。 let totalPrice = priceArr.reduce(function (sum, i) { return sum + i; }, 0) let totalNum = numArr.reduce(function (sum, i) { return sum + i; }, 0) oTotalPrice.innerHTML = totalPrice.toFixed(2); oTotalNum.innerHTML = totalNum; } // 判断提交按钮是否可用 function isBtnSubmitEnabled() { let oCheckedInputs = document.querySelectorAll('.singleCheck:checked'); let result = [...oCheckedInputs].some(function (item) { return item.checked; }) oBtnSubmit.disabled = result ? false : true; } //判断是否要全选 function isCheckAll() { let oCheckedInputs = document.querySelectorAll('.singleCheck:checked'); let oSingleChecks = $All('.singleCheck'); if (oCheckedInputs.length === oSingleChecks.length) { oCheckAlls.forEach(function (item) { item.checked = true; }) } else { oCheckAlls.forEach(function (item) { item.checked = false; }) } } function $(selector) { return document.querySelector(selector); } function $All(selector) { return document.querySelectorAll(selector); } }
发表评论:
◎请发表你卖萌撒娇或一针见血的评论,严禁小广告。