一、原理
将商品加入购物车,实际上是将所选商品信息加入购物车的表里,我们所建的页面表是读取数据库里购物车的数据表,里面加了谁,就将其对应的数据获取出来放到建的页面表中
二、功能实现:
- “全选”复选框:
- 点“全选”前的复选框,将商品全部选择;再点一次,则取消选择
- 将商品全选后,“全选”前的复选框需打勾;只要去掉一个商品,“全选”前复选框的勾则被取消
- 购物车数量:点”-“或”+“按钮,对所选商品数量进行增减
- 结算金额(单价*数量):其中的单价可自定义一个属性(即data-price),获取当前类名称的元素对象,拿索引对索引,取其里面的值;数量为功能2中的val;根据索引对索引,金额的文本内容即为单价与数量相乘
- 将勾选商品的金额放到下面的“合计”中:
- 设置金额的属性(即data-totle),其值为后面每次计算的总值赋给它(即totle[this,index]);
- 将1.写为一个金额的计算方法,传入形参(index,value),在购物车数量的增减事件中调用,并传入实参(this.index,val);
- 合计加总金额时,需判断商品信息前的复选框是否被选中,选中则加,不选中则不加:
(1)添加一个判断商品信息前的复选框是否打勾的方法(即ischoose());
(2)将ischoose()方法在购物车数量的增和减事件、全选复选框的点击事件、全选复选框的点击事件中使用; - 已选商品的数量:在合计时,将所选商品的数量相加后的值给其赋之
三、代码块
html代码:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
table{
border-collapse: collapse; //单元格合并
width: 1000px;
margin: 0 auto;
border: 1px solid silver;
}
.title{
font-size: 14px;
}
.face{
width: 80px;
}
.word{
width: 200px;
font-size: 12px;
color: red;
display: inline-block;
text-decoration: none;
margin-left: 10px;
}
td{
padding: 10px 0;
min-width: 65px;
}
.price{
font-weight: bold;
color: black;
}
.totle{
font-weight: bold;
color: red;
}
tr{
border: 1px solid #d8d8d8;
background-color: #f6f6f6;
}
.btn button{
width: 30px;
height: 30px;
outline: none;
border-style: none;
background-color: #e0e0e0;
}
.btn input{
width: 30px;
height: 30px;
text-align: center;
}
</style>
</head>
<body>
<table>
<tr class="title">
<td><input type="checkbox" class="ckbox">全选</td>
<td>商品信息</td>
<td>单价</td>
<td>数量</td>
<td>金额</td>
<td>操作</td>
</tr>
<tr>
<td><input type="checkbox" class="ckbtn"></td>
<td>
<img src="img/1.jpg" class="face" align="left">
<a href="#" class="word">豫竹香辣牛肉方便面60包 袋装速食干吃面干脆面泡面整箱包邮特价</a>
</td>
<td><span class="price" data-price="39.00">¥39.00</span></td>
<td class="btn"><button class="btnleft">-</button><input class="txt" type="text" value="1"><button class="btnright">+</button></td>
<td><span class="totle" data-totle="39.00">¥39.00</span></td>
<td>删除</td>
</tr>
<tr>
<td><input type="checkbox" class="ckbtn"></td>
<td>
<img src="img/1.jpg" class="face" align="left">
<a href="#" class="word">豫竹香辣牛肉方便面60包 袋装速食干吃面干脆面泡面整箱包邮特价</a>
</td>
<td><span class="price" data-price="39.00">¥39.00</span></td>
<td class="btn"><button class="btnleft">-</button><input class="txt" type="text" value="1"><button class="btnright">+</button></td>
<td><span class="totle" data-totle="39.00">¥39.00</span></td>
<td>删除</td>
</tr>
<tr>
<td><input type="checkbox" class="ckbtn"></td>
<td>
<img src="img/1.jpg" class="face" align="left">
<a href="#" class="word">豫竹香辣牛肉方便面60包 袋装速食干吃面干脆面泡面整箱包邮特价</a>
</td>
<td><span class="price" data-price="39.00">¥39.00</span></td>
<td class="btn"><button class="btnleft">-</button><input class="txt" type="text" value="1"><button class="btnright">+</button></td>
<td><span class="totle" data-totle="39.00">¥39.00</span></td>
<td>删除</td>
</tr>
<tr>
<td><input type="checkbox" class="ckbtn"></td>
<td>
<img src="img/1.jpg" class="face" align="left">
<a href="#" class="word">豫竹香辣牛肉方便面60包 袋装速食干吃面干脆面泡面整箱包邮特价</a>
</td>
<td><span class="price" data-price="39.00">¥39.00</span></td>
<td class="btn"><button class="btnleft">-</button><input class="txt" type="text" value="1"><button class="btnright">+</button></td>
<td><span class="totle" data-totle="39.00">¥39.00</span></td>
<td>删除</td>
</tr>
<tr>
<td><input type="checkbox" class="ckbtn"></td>
<td>
<img src="img/1.jpg" class="face" align="left">
<a href="#" class="word">豫竹香辣牛肉方便面60包 袋装速食干吃面干脆面泡面整箱包邮特价</a>
</td>
<td><span class="price" data-price="39.00">¥39.00</span></td>
<td class="btn"><button class="btnleft">-</button><input class="txt" type="text" value="1"><button class="btnright">+</button></td>
<td><span class="totle" data-totle="39.00">¥39.00</span></td>
<td>删除</td>
</tr>
<tr>
<td><input type="checkbox" class="ckbox">全选</td>
<td colspan="2">已选商品<span class="number">0</span>件</td>
<td>合计:<span class="totleprice">0</span>元</td>
<td colspan="2"><button>结算</button></td>
</tr>
</table>
<script src="js/cart.js"></script>
</body>
</html>
cart.js:
var ckbox = document.getElementsByClassName("ckbox");
var ckbtn = document.getElementsByClassName("ckbtn");
var btnleft = document.getElementsByClassName("btnleft");
var btnright = document.getElementsByClassName("btnright");
var txt = document.getElementsByClassName("txt");
var price=document.getElementsByClassName("price");
var totle=document.getElementsByClassName("totle");
var allprice=document.getElementsByClassName("totleprice")[0];
var number=document.getElementsByClassName("number")[0];
var count=0;
//商品信息前复选框的事件
for(var i=0;i<ckbtn.length;i++){
ckbtn[i].onclick=function(){
if(this.checked){
count++;
}
else{
count--;
}
if(count==ckbtn.length){
ckbox[0].checked=true;
ckbox[1].checked=true;
}
else{
ckbox[0].checked=false;
ckbox[1].checked=false;
}
ischoose();
}
}
//全选复选框的事件
for (key in ckbox) {
ckbox[key].index = key; //给index属性上绑值,绑个索引
ckbox[key].onclick = function () {
ckbox[this.index == 0 ? 1 : 0].checked = !ckbox[this.index == 0 ? 1 : 0].checked;
if(this.checked){
for (var i = 0; i < ckbtn.length; i++) {
ckbtn[i].checked = true;
}
}
else{
for (var i = 0; i < ckbtn.length; i++) {
ckbtn[i].checked = false;
}
}
ischoose();
}
}
//购物车数量的增减事件
for (var i = 0; i < btnleft.length; i++) {
btnleft[i].index = i;
btnleft[i].onclick = function () {
var val = txt[this.index].value;
val--;
if (val < 1) {
val = 1;
}
txt[this.index].value = val;
addprice(this.index,val);
ischoose();
}
btnright[i].index=i;
btnright[i].onclick = function () {
var val=txt[this.index].value;
val++;
txt[this.index].value=val;
addprice(this.index,val);
ischoose();
}
}
//金额的计算方法
function addprice(index,value){
totle[index].innerHTML="¥"+(price[index].getAttribute("data-price")*value).toFixed(2);
totle[index].setAttribute("data-totle",(price[index].getAttribute("data-price")*value).toFixed(2));
}
//判断商品信息前的复选框是否打勾
function ischoose(){
var totleprice=0;
var num=0;
for(var i=0;i<ckbtn.length;i++){
if(ckbtn[i].checked){
totleprice+=parseFloat(totle[i].getAttribute("data-totle"));
num+=parseInt(txt[i].value);
}
}
allprice.innerHTML="¥"+totleprice.toFixed(2);
number.innerHTML=num;
}
四、遇到的问题及解决方法
- 问题:点第一个“全选”按钮时,第二个“全选”按钮自动打钩,反之亦然
解决思路:存值,即给index属性上绑值,绑个索引
解决方法:判断当前index属性的索引,找到其相反的索引值(只有两个“全选”按钮,因此若当前索引为0,找到索引为1的那个;反之亦然),使其复选框前打钩
代码如下:
for (key in ckbox) {
ckbox[key].index = key; //给index属性上绑值,绑个索引
ckbox[key].onclick = function () {
ckbox[this.index == 0 ? 1 : 0].checked = true;
for (var i = 0; i < ckbtn.length; i++) {
ckbtn[i].checked = true;
}
}
}
知识点:ckbox[key].index = key;
Q:事件中,事件里面拿不到外面的索引值,只能拿到最大值,怎样拿到其索引值?
A:法一:做一个闭包处理,有一个自执行函数
法二:在事件外面做一个桥梁,在绑事件的同时,把它所对应的索引绑到当前对象的索引属性上,事件里面直接拿它的索引属性,即当前对象的索引
-
问题:单击“全选”前的复选框,进行总金额合计时,默认为NaN
解决方法:给<td><span class="totle" data-totle="">¥39.00</span></td>
中的data-totle属性需设置默认值 -
问题:单击“全选”前的复选框,进行总金额合计时,已经选过一次之后,若想修改商品数量,则合计中的金额数没有发生改变
解决方法:将判断商品信息前的复选框是否打勾的方法(即ischoose())在“-”和“+”的点击事件中调用 -
问题:不单击“全选”复选框,进行总金额计算时,若只选了几个,则合计中的金额数没有发生变化
解决思路:给商品前的复选框添加一个点击事件,事件中调用ischoose() -
问题:将商品信息前的复选框选择之后,又去点“全选”前的复选框,发现变成反选(即商品信息前的复选框中,之前没被选择过的打勾,之前被选择过的勾被取消)
解决方法:将for循环中的ckbtn[i].checked = !ckbtn[i].checked;
改为ckbtn[i].checked=true;
-
问题:将商品全选之后,若想取消一个商品,则全选前的复选框依然打勾
解决思路:点击商品与商品信息前”复选框“的长度相等之后,让”全选“复选框全部选择;只要点击商品的长度比其少,则让其不选择
用户可能同一件商品连续点击几次,因此需判断当前点的商品是否重复
解决方法:
(1)定义一个全局变量(即count),若当前商品被选择,则count++;若被选择后又取消,则count- -
(2)将count与商品信息前”复选框“的长度进行判断:若相等,则两个“全选”复选框被选择,为true;否则,为false
(3)反选后,count需清零(若不清零,则第一次全选后取消,再进行全选,两个“全选”复选框将不会打勾)