1、静态页面
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<style type="text/css">
* {
margin: 0;
padding: 0;
text-decoration: none;
list-style: none;
}
body {
background: #ea4335;
}
.main {
width: 800px;
margin: auto;
margin-top: 20px;
}
.top {
background: #fff;
padding: 10px;
}
.ipt {
width: 230px;
height: 32px;
line-height: 32px;
border: 1px solid #ccc;
}
.btn {
height: 34px;
width: 120px;
border: none;
}
.cart {
background: #fff;
margin-top: 20px;
padding: 10px;
}
.cart .tr {
height: 35px;
}
.cart .tr div {
float: left;
line-height: 35px;
}
.cart .tr {
padding: 5px 0px;
border-bottom: 1px solid #ccc;
}
.cart .tr {
clear: both;
}
.cart .tr div:nth-child(1) {
width: 20%;
}
.cart .tr div:nth-child(2) {
width: 20%;
}
.cart .tr div:nth-child(3) {
width: 20%;
}
.cart .tr div:nth-child(4) {
width: 30%;
}
.cart .tr div:nth-child(5) {
width: 10%;
}
.cart .tr input {
width: 50px;
}
.footer {
background: #fff;
margin-top: 20px;
padding: 10px;
}
#amount {
color: red;
}
</style>
</head>
<body>
<div class="main">
<div class="top">
商品名称:<input type="text" name="" value="" id="title" class="ipt" /> 商品价格:<input type="text" name="" value="" id="price" class="ipt" />
<input type="button" value="加入购物车" class="btn" id="addcart" />
</div>
<div class="cart">
<div class="tr">
<div><input type="checkbox" name="" value="" id="selectAll" /> 全选按钮</div>
<div>商品名称</div>
<div>商品价格</div>
<div>数量</div>
<div>操作</div>
</div>
<div id="goods">
<div class="tr" id="1655771835688">
<div><input type="checkbox" name="ckboxs" value="1655771835688" /></div>
<div>鼠标</div>
<div>100元</div>
<div>
<a href="javascript:;" name="-">-</a>
<input type="text" value="1" readonly="" />
<a href="javascript:;" name="+">+</a>
</div>
<div><a href="javascript:;" name="del">删除</a></div>
</div>
</div>
</div>
<div class="footer">
总共<span id="count">0</span>件商品,共计 <span id="amount">0</span> 元
<a href="javascript:;" class="r" id="delall">清空购物车</a>
</div>
</div>
</body>
</html>
2、模拟数据、渲染数据
class Cart {
// 1、模拟数据
goods = [
{ id: 1, title: "电脑", price: 100, num: 1, checked: true },
{ id: 2, title: "鼠标", price: 50, num: 1, checked: false },
{ id: 3, title: "键盘", price: 80, num: 1, checked: true },
];
//获取goods节点
goodsNode = document.getElementById("goods");
//渲染数据
render(h) {
var str = "";
for (var i = 0; i < this.goods.length; i++) {//循环拼接结构
str += ` <div class="tr" id="${this.goods[i].id}">
<div><input type="checkbox" name="ckboxs" value="1655771835688" ${this.goods[i].checked?'checked':''} /></div>
<div>${this.goods[i].title}</div>
<div>${this.goods[i].price}元</div>
<div>
<a href="javascript:;" name="-">-</a>
<input type="text" value="${this.goods[i].num}" readonly="" />
<a href="javascript:;" name="+">+</a>
</div>
<div><a href="javascript:;" name="del">删除</a></div>
</div>`;
}
this.goodsNode.innerHTML = str;
}
}
var mycart = new Cart();
mycart.render();
3、点击购物车,添加商品
class Cart {
// 1、模拟数据
goods = [
{ id: 1, title: "电脑", price: 100, num: 1, checked: true },
{ id: 2, title: "鼠标", price: 50, num: 1, checked: false },
{ id: 3, title: "键盘", price: 80, num: 1, checked: true },
];
//constructor 初始化执行
constructor() {
this.render();
this.addevent();
}
//获取goods节点
goodsNode = document.getElementById("goods");
//3.1 获取添加购物车按钮节点
addcartNode = document.getElementById("addcart");
// 3.4 获取商品名,商品价格输入框节点
titleNode = document.getElementById("title");
priceNode = document.getElementById("price");
//所有监听事件的函数
addevent() {
// 3.3 保存当前实例的this
var _this = this;
// 3.2 addcart添加购物车按钮的点击事件
this.addcartNode.addEventListener("click", function () {
// console.log(this); //注意,此时的this是addcart按钮
//3.5获取用户输入的商品名以及价格,传递给保存数据函数,注意一个函数只做一件事
var title = _this.titleNode.value;
var price = _this.priceNode.value;
//3.9、如果用户输入为空,则返回
if (title == "" || price == "") return;
// console.log(title,price);
_this.saveData(title, price);
//3.8 添加完数据后,将输入框内容变为空
_this.titleNode.value = "";
_this.priceNode.value = "";
});
}
//3.6 saveData
saveData(title, price) {
var obj = {
id: Date.now(),
title: title,
price: price,
num: 1,
checked: true,
};
this.goods.unshift(obj);
// 3.7 数据准备好后,重新渲染函数
// console.log(this.goods);
this.render();
}
//2、渲染数据
render(h) {
······
}
}
var mycart = new Cart();
mycart.render();
4、修改复选框状态
class Cart {
// 1、模拟数据
goods = [
{ id: 1, title: "电脑", price: 100, num: 1, checked: true },
{ id: 2, title: "鼠标", price: 50, num: 1, checked: false },
{ id: 3, title: "键盘", price: 80, num: 1, checked: true },
];
//constructor 初始化执行
constructor() {
this.render();
this.addevent();
}
//获取goods节点
goodsNode = document.getElementById("goods");
·····
//所有监听事件的函数
addevent() {
·····
// 4、监听复选框状态,采用事件委托,监听goodsNode
this.goodsNode.addEventListener("click", function (e) {
//4.1 e.target.name 获取目标对象身上的name属性,用来标识点击对象的不同,从而有不同的处理逻辑
if (e.target.name == "ckboxs") {
// 4.2 获取点击按钮的id,以及状态,传递给修改函数,进行数据的修改
var id = e.target.parentNode.parentNode.id;
var checked = e.target.checked;
// console.log(id, checked);
_this.editDate(id, "checked", checked);
}
});
}
// 4.3 、修改数据函数,修改哪个id,哪个属性,哪个值
editDate(id, key, value) {
// 4.4遍历数据,筛选出,要修改哪条数据,然后把对应属性以及属性值修改了
for (let index = 0; index < this.goods.length; index++) {
if (this.goods[index].id == id) {
this.goods[index][key] = value;
}
}
// 4.4 修改后,需要重新渲染
this.render();
// console.log(this.goods);
}
······
5、修改+ -
//所有监听事件的函数
addevent() {
·····
// 5.1 、监听+ -
if (e.target.name == "+" || e.target.name == "-") {
// 5.2 拿到修改值的id,以及num的值
var id = e.target.parentNode.parentNode.id;
var num;
for (let index = 0; index < _this.goods.length; index++) {
if (_this.goods[index].id == id) {
num = _this.goods[index].num;
}
}
// 5.3判断点击的是+,还是-,进行数字的改变
if (e.target.name == "+") {
num++;
} else {
num--;
}
if (num <= 0) {
num = 1;
}
// 5.4 将准备的ID,num传递该修改数据函数
_this.editDate(id, "num", num);
}
});
}
6、删除商品
//所有监听事件的函数
addevent() {
····
//6、1删除商品
if ((e.target.name = "del")) {
//6.2 获取点击删除按钮的id
var id = e.target.parentNode.parentNode.id;
//6.3 将准备好的id传递给删除函数
_this.delData(id);
}
});
}
//6、删除数据函数 id,删除哪个数据
delData(id) {
// 方法一:
// var newData = [];
// for (let index = 0; index < this.goods.length; index++) {
// if (id != this.goods[index].id) {
// newData.push(this.goods[index]);
// }
// }
// this.goods = newData;
// this.render();
// 方法二:
this.goods = this.goods.filter(function (item) {
return item.id != id;
});
this.render();
}
7、全选与反选
// 4、监听复选框状态,采用事件委托,监听goodsNode
this.goodsNode.addEventListener("click", function (e) {
·····
// 7、全选按钮
this.selectAllNode.addEventListener("click", function (e) {
//7.2 获取全选按钮的状态,全选按钮的状态跟每个商品的状态一直
var isAllChecked = e.target.checked;
//7.3 传递全选状态给处理函数
_this.selectAll(isAllChecked);
});
}
//7.4、全选与反全选
selectAll(isAllChecked) {
for (let index = 0; index < this.goods.length; index++) {
this.goods[index].checked = isAllChecked;
}
this.render();
}
8、选中全部的单选,全选
//所有监听事件的函数
addevent() {
·····
// 4、监听复选框状态,采用事件委托,监听goodsNode
this.goodsNode.addEventListener("click", function (e) {
······
// 8.1、监听复选框状态,如果全部为true,则全选按钮为true
_this.editSelectAll();
}
});
·····
// 8.2、处理单选与全选交互
editSelectAll() {
// 第一种写法
// var checked = true; //默认checed状态为true
// for (let index = 0; index < this.goods.length; index++) {
// // 只要商品的单选框没有有没有被选中,则将checked变为false
// if (!this.goods[index].checked) {
// checked = false;
// }
// }
// //改变selectAllNode的状态
// this.selectAllNode.checked = checked;
// 第二种写法:
var goodCheck = 0;
for (let index = 0; index < this.goods.length; index++) {
if (this.goods[index].checked) {
goodCheck += 1;
}
}
if (this.goods.length == goodCheck) {
this.selectAllNode.checked = true;
} else {
this.selectAllNode.checked = false;
}
}
9、清空购物车
// 9.1 获取清空购物车按钮
delallNode = document.getElementById("delall");
//所有监听事件的函数
addevent() {
·····
// 9、清空购物车
this.delallNode.addEventListener("click", function () {
_this.goods=[]
_this.render()
});
}
10、计算商品总数量、总价
//10.1 获取商品件数,商品总价节点
countNode = document.getElementById("count");
amountNode = document.getElementById("amount");
····
//10、计算底部数据,在初次渲染函数render中,进行渲染,后面,随着用户的操作,也会随着冲洗渲染
changeFooter() {
// 计算底部商品件数
var count = 0;
var amount = 0;
for (let index = 0; index < this.goods.length; index++) {
if (this.goods[index].checked) {
count += this.goods[index].num;
amount += this.goods[index].num * this.goods[index].price;
}
}
this.countNode.innerHTML = count;
this.amountNode.innerHTML = amount;
}
11、本地存储
//constructor 初始化执行
constructor() {
// 初始化时,从本地拿去数据
this.goods = localStorage.getItem("goods") ? JSON.parse(localStorage.getItem("goods")) : [];
this.render();
this.addevent();
// 全选按钮,也需要初始化时
this.editSelectAll()
}
````
//2、渲染数据
render() {
var str = "";
for (var i = 0; i < this.goods.length; i++) {
str += `
<div class="tr" id="${this.goods[i].id}">
<div><input type="checkbox" name="ckboxs" value="1655771835688" ${this.goods[i].checked ? "checked" : ""} /></div>
<div>${this.goods[i].title}</div>
<div>${this.goods[i].price}元</div>
<div>
<a href="javascript:;" name="-">-</a>
<input type="text" value="${this.goods[i].num}" readonly="" />
<a href="javascript:;" name="+">+</a>
</div>
<div><a href="javascript:;" name="del">删除</a></div>
</div>`;
}
this.goodsNode.innerHTML = str;
// 调用商品总数量,以及总价格
this.changeFooter();
// 保存数据到本地
localStorage.setItem("goods", JSON.stringify(this.goods));
}
12、es6完整js代码
let _this;
class Cart {
// 1、模拟数据
/*
{ id: 1, title: "电脑", price: 100, num: 1, checked: true },
{ id: 2, title: "鼠标", price: 50, num: 2, checked: false },
{ id: 3, title: "键盘", price: 80, num: 1, checked: true },
*/
goods = [];
//获取goods节点
goodsNode = document.getElementById("goods");
//3.1 获取添加购物车按钮节点
addcartNode = document.getElementById("addcart");
// 3.4 获取商品名,商品价格输入框节点
titleNode = document.getElementById("title");
priceNode = document.getElementById("price");
//7.1 获取全选按钮
selectAllNode = document.getElementById("selectAll");
// 9.1 获取清空购物车按钮
delallNode = document.getElementById("delall");
//10.1 获取商品件数,商品总价节点
countNode = document.getElementById("count");
amountNode = document.getElementById("amount");
//constructor 初始化执行
constructor() {
_this = this;
// 初始化时,从本地拿去数据
this.goods = localStorage.getItem("goods") ? JSON.parse(localStorage.getItem("goods")) : [];
this.render();
this.addevent();
// 全选按钮,也需要初始化时
this.editSelectAll();
}
//所有监听事件的函数
addevent() {
// 3.3 保存当前实例的this
// 3.2 addcart添加购物车按钮的点击事件
this.addcartNode.addEventListener("click", function () {
// console.log(this); //注意,此时的this是addcart按钮
//3.5获取用户输入的商品名以及价格,传递给保存数据函数,注意一个函数只做一件事
var title = _this.titleNode.value;
var price = _this.priceNode.value;
//3.9、如果用户输入为空,则返回
if (title == "" || price == "") return;
// console.log(title,price);
_this.saveData(title, price);
// 调用是否全选
_this.editSelectAll();
//3.8 添加完数据后,将输入框内容变为空
_this.titleNode.value = "";
_this.priceNode.value = "";
});
// 4、监听复选框状态,采用事件委托,监听goodsNode
this.goodsNode.addEventListener("click", function (e) {
//4.1 e.target.name 获取目标对象身上的name属性,用来标识点击对象的不同,从而有不同的处理逻辑
if (e.target.name == "ckboxs") {
// 4.2 获取点击按钮的id,以及状态,传递给修改函数,进行数据的修改
var id = e.target.parentNode.parentNode.id;
var checked = e.target.checked;
// console.log(id, checked);
_this.editDate(id, "checked", checked);
// 8、监听复选框状态,如果全部为true,则全选按钮为true
_this.editSelectAll();
}
//5.1 、监听+ -
if (e.target.name == "+" || e.target.name == "-") {
// 5.2 拿到修改值的id,以及num的值
var id = e.target.parentNode.parentNode.id;
var num;
for (let index = 0; index < _this.goods.length; index++) {
if (_this.goods[index].id == id) {
num = _this.goods[index].num;
}
}
// 5.3判断点击的是+,还是-,进行数字的改变
if (e.target.name == "+") {
num++;
} else {
num--;
}
if (num <= 0) {
num = 1;
}
// 5.4 将准备的ID,num传递该修改数据函数
_this.editDate(id, "num", num);
}
//6、1删除商品
if (e.target.name == "del") {
//6.2 获取点击删除按钮的id
var id = e.target.parentNode.parentNode.id;
//6.3 将准备好的id传递给删除函数
_this.delData(id);
}
});
// 7、全选按钮
this.selectAllNode.addEventListener("click", function (e) {
//7.2 获取全选按钮的状态,全选按钮的状态跟每个商品的状态一直
var isAllChecked = e.target.checked;
//7.3 传递全选状态给处理函数
_this.selectAll(isAllChecked);
});
// 9、清空购物车
this.delallNode.addEventListener("click", function () {
_this.goods = [];
_this.render();
});
}
//10、计算底部数据,在初次渲染函数render中,进行渲染,后面,随着用户的操作,也会随着冲洗渲染
changeFooter() {
// 计算底部商品件数
var count = 0;
var amount = 0;
for (let index = 0; index < this.goods.length; index++) {
if (this.goods[index].checked) {
count += this.goods[index].num;
amount += this.goods[index].num * this.goods[index].price;
}
}
this.countNode.innerHTML = count;
this.amountNode.innerHTML = amount;
}
// 8、处理单选与全选交互
editSelectAll() {
// 第一种写法
// var checked = true; //默认checed状态为true
// for (let index = 0; index < this.goods.length; index++) {
// // 只要商品的单选框没有有没有被选中,则将checked变为false
// if (!this.goods[index].checked) {
// checked = false;
// }
// }
// //改变selectAllNode的状态
// this.selectAllNode.checked = checked;
// 第二种写法:
var goodCheck = 0;
for (let index = 0; index < this.goods.length; index++) {
if (this.goods[index].checked) {
goodCheck += 1;
}
}
if (this.goods.length != goodCheck || this.goods.length == 0) {
this.selectAllNode.checked = false;
} else {
this.selectAllNode.checked = true;
}
}
//7.4、全选与反全选
selectAll(isAllChecked) {
for (let index = 0; index < this.goods.length; index++) {
this.goods[index].checked = isAllChecked;
}
this.render();
}
//6、删除数据函数 id,删除哪个数据
delData(id) {
// // 方法一:
// // var newData = [];
// // for (let index = 0; index < this.goods.length; index++) {
// // if (id != this.goods[index].id) {
// // newData.push(this.goods[index]);
// // }
// // }
// // this.goods = newData;
// // this.render();
// // 方法二:
this.goods = this.goods.filter(function (item) {
return item.id != id;
});
_this.editSelectAll();
this.render();
}
// 4.3 、修改数据函数,修改哪个id,哪个属性,哪个值
editDate(id, key, value) {
// 4.4遍历数据,筛选出,要修改哪条数据,然后把对应属性以及属性值修改了
for (let index = 0; index < this.goods.length; index++) {
if (this.goods[index].id == id) {
this.goods[index][key] = value;
}
}
// 4.4 修改后,需要重新渲染
this.render();
// console.log(this.goods);
}
//3.6 saveData 保存数据
saveData(title, price) {
var obj = {
id: Date.now(),
title: title,
price: price,
num: 1,
checked: true,
};
this.goods.unshift(obj);
// 3.7 数据准备好后,重新渲染函数
// console.log(this.goods);
this.render();
}
//2、渲染数据
render() {
var str = "";
for (var i = 0; i < this.goods.length; i++) {
str += `
<div class="tr" id="${this.goods[i].id}">
<div><input type="checkbox" name="ckboxs" value="1655771835688" ${this.goods[i].checked ? "checked" : ""} /></div>
<div>${this.goods[i].title}</div>
<div>${this.goods[i].price}元</div>
<div>
<a href="javascript:;" name="-">-</a>
<input type="text" value="${this.goods[i].num}" readonly="" />
<a href="javascript:;" name="+">+</a>
</div>
<div><a href="javascript:;" name="del">删除</a></div>
</div>`;
}
this.goodsNode.innerHTML = str;
// 调用商品总数量,以及总价格
this.changeFooter();
// 保存数据到本地
localStorage.setItem("goods", JSON.stringify(this.goods));
}
}
var mycart = new Cart();
mycart.render();
13、es5购物车完整代码
let addcart = document.getElementById("addcart"); //加入购物车
let title = document.getElementById("title"); //商品名
let price = document.getElementById("price"); //价格
let goods = document.getElementById("goods"); //商品列表
let selectAll = document.getElementById("selectAll"); //全选
let delallElement = document.getElementById("delall"); //清空购物车
// 点击添加
addcart.addEventListener("click", addcartFun);
function addcartFun() {
let titleValue = title.value;
let priceValue = price.value;
let str = `
<div class="tr" id="${+new Date()}">
<div><input type="checkbox" name="ckboxs" value="1655771835688" /></div>
<div>${titleValue}</div>
<div>${priceValue}元</div>
<div>
<a href="javascript:;" name="-">-</a>
<input type="text" value="1" readonly="" />
<a href="javascript:;" name="+">+</a>
</div>
<div><a href="javascript:;" name="del">删除</a></div>
</div>
`;
goods.insertAdjacentHTML("beforeend", str);
// 重新计算总量和价格
aountNumandPrice();
}
goods.addEventListener("click", clickgoodsFun);
function clickgoodsFun(e) {
// 点击删除按钮
if (e.target.name == "del") {
let tr = e.target.parentNode.parentNode;
tr.parentNode.removeChild(tr);
// 重新判断是否要全选
ckboxChangeSelectAll();
// 重新计算总量和价格
aountNumandPrice();
}
//点击+
if (e.target.name == "+") {
let numInputValue = e.target.previousElementSibling.value;
numInputValue++;
e.target.previousElementSibling.value = numInputValue;
// 重新计算总量和价格
aountNumandPrice();
}
//点击-
if (e.target.name == "-") {
let numInputValue = e.target.nextElementSibling.value;
if (numInputValue >= 2) numInputValue--;
e.target.nextElementSibling.value = numInputValue;
// 重新计算总量和价格
aountNumandPrice();
}
//点击单选框
if (e.target.name == "ckboxs") {
ckboxChangeSelectAll();
// 重新计算总量和价格
aountNumandPrice();
}
// 点击单选是否要全选
function ckboxChangeSelectAll() {
selectAll.checked = true;
let ckboxsAll = document.getElementsByName("ckboxs");
for (let i = 0; i < ckboxsAll.length; i++) {
if (!ckboxsAll[i].checked) {
selectAll.checked = false;
}
}
}
}
// 全选按钮
selectAll.addEventListener("click", selectAllFun);
function selectAllFun() {
let isChecked = selectAll.checked;
let ckboxsAll = document.getElementsByName("ckboxs");
for (let i = 0; i < ckboxsAll.length; i++) {
ckboxsAll[i].checked = isChecked;
}
// 重新计算总量和价格
aountNumandPrice();
}
// 统计数据
function aountNumandPrice() {
let countElement = document.getElementById("count");
let amountElement = document.getElementById("amount");
let count = 0;
let amount = 0;
for (let i = 0; i < goods.children.length; i++) {
// 是否被选中
let isChecked = goods.children[i].children[0].children[0].checked;
if (isChecked) {
let num = +goods.children[i].children[3].children[1].value;
let price = parseInt(goods.children[i].children[2].innerHTML);
count += num;
amount += num * price;
}
}
countElement.innerHTML = count;
amountElement.innerHTML = amount;
}
aountNumandPrice();
// 清空所有商品
delallElement.addEventListener("click", delallFun);
function delallFun() {
goods.innerHTML = "";
aountNumandPrice();
}