本文枯燥乏味,偏长,请耐心
案例的效果图
html部分 ...
<div class="header">页面顶部</div>
<div class="content">
<!-- <div class="top">
<input type="checkbox"> 全选
</div>
<ul>
<li>
<div class="status">
<input type="checkbox">
</div>
<div class="show">
<img src="" alt="">
</div>
<div class="title">
asdhgaskjhdgkjasd
</div>
<div class="price">
¥ 100.00
</div>
<div class="number">
<button>-</button>
<input type="text" value="1">
<button>+</button>
</div>
<div class="sub">
¥ 100.00
</div>
<div class="destory">
<button>删除</button>
</div>
</li>
</ul>
<div class="bottom">
<div class="totalNum">
总件数 : 3
</div>
<div class="btns">
<button>清空购物车</button>
<button>去结算</button>
<button>删除所有已选中</button>
</div>
<div class="totalPrice">
总价格 : ¥ <span>100.00</span>
</div>
</div> -->
</div>
<div class="footer">页面底部</div>
<script src="./index.js"></script>
...
css部分 ...
* {
margin: 0;
padding: 0;
}
ul,
ol,
li {
list-style: none;
}
.header,
.footer {
width: 1200px;
height: 100px;
background-color: skyblue;
color: #fff;
font-size: 50px;
display: flex;
justify-content: center;
align-items: center;
margin: 0 auto;
}
.footer {
height: 400px;
}
.content {
width: 1200px;
margin: 0 auto;
padding: 10px 0;
}
.content > .top,
.content > .bottom {
height: 50px;
background-color: pink;
display: flex;
align-items: center;
}
.content > .bottom {
justify-content: space-between;
box-sizing: border-box;
padding: 0 10px;
}
.content > .bottom > .totalPrice > span {
font-size: 20px;
color: red;
}
.content > .bottom > .btns > button {
font-size: 18px;
padding: 5px 10px;
cursor: pointer;
}
.content > .top > input {
width: 30px;
height: 30px;
margin: 0 15px 0 50px;
}
.content > ul {
padding-top: 10px;
}
.content > ul > li {
width: 100%;
border: 1px solid #333;
box-sizing: border-box;
height: 100px;
margin-bottom: 10px;
display: flex;
}
.content > ul > li > div {
display: flex;
justify-content: center;
align-items: center;
border-right: 1px solid #333;
}
.content > ul > li > div:last-child {
border: none;
}
.content > ul > li > .show,
.content > ul > li > .status {
width: 100px;
}
.content > ul > li > .status > input {
width: 30px;
height: 30px;
}
.content > ul > li > .show > img {
width: 100%;
height: 100%;
display: block;
}
.content > ul > li > .price,
.content > ul > li > .sub {
width: 200px;
color: red;
font-size: 20px;
}
.content > ul > li > .title {
width: 300px;
align-items: flex-start;
justify-content: flex-start;
box-sizing: border-box;
padding: 5px;
}
.content > ul > li > .number {
width: 230px;
}
.content > ul > li > .number > input {
width: 50px;
height: 30px;
text-align: center;
margin: 0 5px;
border: none;
outline: none;
font-size: 18px;
}
.content > ul > li > .number > button {
width: 30px;
height: 30px;
cursor: pointer;
}
.content > ul > li > .destory {
flex: 1;
}
.content > ul > li > .destory > button {
padding: 5px;
font-size: 18px;
cursor: pointer;
}
...
js部分 ...
数组数据分析
* 1. id: 数据的唯一值
* 2. status: true代表该商品被选中, false则为没被选中
* 3. pic: 图片地址
* 4. name: 商品名
* 5. price: 价格
* 6. number: 商品收藏数量
* 7. total: 库存
*
*
* 数据驱动视图
* 套路:
* 查: 查询数据, 渲染到页面
* 增删改: 找到源数据, 然后对源数据做修改, 修改完成, 重新渲染页面
*
*
* 1. 将通过数据重构页面
* 1.1 查询数据, 渲染页面
* 2. 全选
* 2.1 选中全选按钮后, 根据全选按钮的选中状态, 修改所有商品的选中状态
* 2.2 重新渲染视图
* 3. 清空购物车
* 3.1 清空商品数据
* 3.2 重新渲染视图
* 4. 结算 (将所选择商品总价计算出后打印到控制台)
* 4.1 找到所有选中的商品
* 4.2 计算所有选中商品各自的总价
* 4.3 计算所有选中商品的总价之和
* 4.4 打印到控制台
* 5. 删除已选中
* 5.1 在原数组中, 找到选中的商品, 然后删除
* 5.2 重新渲染视图
* 6. 商品数量调整
* 6.1 找到对应的商品, 修改收藏数量
* 6.2 重新渲染视图
* 7. 选中商品
* 7.1 找到对应的商品, 修改选中状态
* 7.2 重新渲染视图
* 8. 删除某一项
* 8.1 找到对应商品, 将删除
* 8.2 重新渲染视图
* 9. 数据持久化 (浏览器关闭, 数据能保存)
* 9.1 本地存储
*
*
* 逻辑:
* 1. 准备一个渲染函数
* 2. 首次打开页面时 调用
* 3. 在各种事件触发之后, 重新调用
*/
// 0. 模拟从后端请求回来的商品数据
// var cartList = [
// // 每一个对象就是一个购物车内容的数据
// {
// id: 111234,
// status: true,
// pic: "https://img1.baidu.com/it/u=2511310783,721605137&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=332",
// name: "我是一个手机, 不知道是啥",
// price: 100,
// number: 3,
// total: 16,
// },
// {
// id: 123456,
// status: false,
// pic: "https://img1.baidu.com/it/u=1537709578,2453227648&fm=253&fmt=auto&app=120&f=JPEG?w=809&h=500",
// name: "我是一个电脑, 不知道是啥",
// price: 98.72,
// number: 1,
// total: 7,
// },
// {
// id: 965874,
// status: true,
// pic: "https://img2.baidu.com/it/u=3561506717,735421650&fm=253&fmt=auto&app=138&f=JPEG?w=750&h=500",
// name: "我是一个手纸, 不知道是啥",
// price: 356.21,
// number: 2,
// total: 22,
// },
// ];
// 获取localStorage的数据时, 为了避免首次进入页面没有数据, 所以通过逻辑或给一个本地数据兜底
var cartList = JSON.parse(window.localStorage.getItem("cartList")) || [
// 每一个对象就是一个购物车内容的数据
{
id: 111234,
status: true,
pic: "https://img1.baidu.com/it/u=2511310783,721605137&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=332",
name: "我是一个手机, 不知道是啥",
price: 100,
number: 3,
total: 16,
},
{
id: 123456,
status: false,
pic: "https://img1.baidu.com/it/u=1537709578,2453227648&fm=253&fmt=auto&app=120&f=JPEG?w=809&h=500",
name: "我是一个电脑, 不知道是啥",
price: 98.72,
number: 1,
total: 7,
},
{
id: 965874,
status: true,
pic: "https://img2.baidu.com/it/u=3561506717,735421650&fm=253&fmt=auto&app=138&f=JPEG?w=750&h=500",
name: "我是一个手纸, 不知道是啥",
price: 356.21,
number: 2,
total: 22,
},
];
// 0. 获取元素
var content = document.querySelector(".content");
// 0. 准备变量
// 1. 准备渲染函数
function bindHtml() {
var selctItem = 0; // 存储选中商品的数量
var selctTotalNum = 0; // 存储选中商品的总数量
var totalPrice = 0; // 存储选中商品的总价
// 1.0 找到选中商品
cartList.forEach(function (item) {
if (item.status) {
// console.log(item)
selctItem++;
selctTotalNum += item.number;
totalPrice += item.number * item.price;
}
});
// 1.1 查询数据, 渲染页面
var str = `<div class="top">
<input class="selcet_all" type="checkbox" ${
// 选中的商品数量如果等于商品数量, 代表所有商品被选中
selctItem === cartList.length ? "checked" : ""
}> 全选
</div>
<ul>`;
cartList.forEach(function (item) {
str += `<li>
<div class="status">
<input data-id="${item.id}" class="item" type="checkbox" ${
item.status ? "checked" : ""
}>
</div>
<div class="show">
<img src="${item.pic}" alt="">
</div>
<div class="title">
${item.name}
</div>
<div class="price">
¥ ${item.price.toFixed(2)}
</div>
<div class="number">
<button class="sub_btn" data-id=${item.id}>-</button>
<input type="text" value="${item.number}">
<button class="add_btn" data-id="${item.id}">+</button>
</div>
<div class="sub">
¥ ${(item.number * item.price).toFixed(2)}
</div>
<div class="destory">
<button data-id="${item.id}" class="del">删除</button>
</div>
</li>`;
});
str += `</ul>
<div class="bottom">
<div class="totalNum">
总件数 : ${selctTotalNum}
</div>
<div class="btns">
<button class="clear">清空购物车</button>
<button class="go_pay" data-TotalPrice="${totalPrice}">去结算</button>
<button class="del_item">删除所有已选中</button>
</div>
<div class="totalPrice">
总价格 : ¥ <span>${totalPrice.toFixed(2)}</span>
</div>
</div>`;
content.innerHTML = str;
// 4. 将数据存储至 localStorage 一份, 以便下次进入是可以获取上一次的数据
window.localStorage.setItem("cartList", JSON.stringify(cartList));
}
// 2. 首次打开页面, 调用渲染函数
bindHtml();
// 3. 利用事件冒泡, 将所有的事件委托给统一的父级
content.onclick = function (e) {
// console.log(e.target.className)
// 3.1 全选按钮事件
if (e.target.className === "selcet_all") {
// 3.1.1 选中全选按钮后, 根据全选按钮的选中状态, 修改所有商品的选中状态
cartList.forEach(function (item) {
item.status = e.target.checked;
});
// 3.1.2 重新渲染视图
bindHtml();
}
// 3.2 清空购物车
if (e.target.className === "clear") {
var boo = confirm("请问您确定清空吗");
if (boo) {
// 3.2.1 清空购物车数据
cartList = [];
// 3.2.2 重新渲染页面
bindHtml();
}
}
// 3.3 结算 (将所选择商品总价计算出后打印到控制台)
if (e.target.className === "go_pay") {
// 3.3.1 在 bindHtml 渲染页面时, 将计算好的总价 放置在标签中, 此时只需要获取到标签上的属性, 打印即可
console.log(e.target.dataset.totalprice);
}
// 3.4 删除已选中 (没有选中项时 禁止执行)
if (e.target.className === "del_item") {
var boo = confirm("请问您确定删除已选中吗");
if (boo) {
// 3.4.1 过滤数组, 只留下选中状态为 false 的
cartList = cartList.filter(function (item) {
return !item.status;
});
// 3.4.2 重新渲染视图
bindHtml();
}
}
// 3.5.1 减少商品数量
if (e.target.className === "sub_btn") {
// 3.5.1.1 减少商品数量, 不能为0
cartList.forEach(function (item) {
// 通过商品ID找到点击的是哪一个商品, 然后给对应商品的数量减1
if (item.id == e.target.dataset.id && item.number >= 2) {
item.number--;
}
});
// 3.5.1.2 重新渲染视图
bindHtml();
}
// 3.5.2 增加商品数量
if (e.target.className === "add_btn") {
// 3.5.2.1 增加商品数量
cartList.forEach(function (item) {
// 通过商品ID找到点击的是哪一个商品, 然后给对应商品的数量加1
if (item.id == e.target.dataset.id && item.number < item.total) {
item.number++;
}
});
// 3.5.2.2 重新渲染视图
bindHtml();
}
// 3.6 选中商品
if (e.target.className === "item") {
// 3.6.1 遍历数组找到要修改的商品
cartList.forEach(function (item) {
if (item.id == e.target.dataset.id) {
// 修改商品的选中状态
item.status = !item.status;
}
});
// 3.6.2 重新渲染视图
bindHtml();
}
// 3.7 删除某一项
if (e.target.className === "del") {
var boo = confirm("请问您确定删除当前项吗");
// 3.7.0 询问用户是否需要删除
if (!boo) return;
// 3.7.1 遍历数组, 找到需要删除的项, 将其过滤掉
cartList = cartList.filter(function (item) {
return item.id != e.target.dataset.id;
});
// 3.7.2 重新渲染视图
bindHtml();
}
};
...