以前写购物车,总是或多或少会留下几个小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);
}
}
发表评论:
◎请发表你卖萌撒娇或一针见血的评论,严禁小广告。