一、案例效果

1、将通过数据重构页面

  • 查询数据, 渲染页面

2、全选

  1. 选中全选按钮后, 根据全选按钮的选中状态, 修改所有商品的选中状态
  2. 重新渲染视图

3、清空购物车

  1. 清空商品数据
  2. 重新渲染视图

4、结算

  1. 找到所有选中的商品
  2. 计算所有选中商品各自的总价
  3. 计算所有选中商品的总价之和

5、删除已选中

  1. 在原数组中, 找到选中的商品, 然后删除
  2. 重新渲染视图

6、商品数量调整

  1. 找到对应的商品, 修改收藏数量
  2. 重新渲染视图

7、选中商品

  1. 找到对应的商品, 修改选中状态
  2. 重新渲染视图

8、删除某一项

  1. 找到对应商品, 将删除
  2. 重新渲染视图

9、数据持久化 (浏览器关闭, 数据能保存)

  • 本地存储

二、案例分析

1. 数组数据分析

  1. id: 数据的唯一值
  2. status: true代表该商品被选中, false则为没被选中
  3. pic: 图片地址
  4. name: 商品名
  5. price: 价格
  6. number: 商品收藏数量
  7. total: 库存

2. 数据驱动视图

  • 查: 查询数据, 渲染到页面
  • 增删改: 找到源数据, 然后对源数据做修改, 修改完成, 重新渲染页面

3. 逻辑思维

  1. 准备一个渲染函数
  2. 首次打开页面时 调用
  3. 在各种事件触发之后, 重新调用

三、html代码

<div class="header">页面顶部</div><div class="content"></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 > .destroy {flex: 1;}.content > ul > li > .destroy > button {padding: 5px;font-size: 18px;cursor: pointer;}

五、js代码的实现

// 获取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" />,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,},];// 1. 获取标签对称const oContent = document.querySelector('.content');// 2. 封装函数 渲染页面function myPage() {// 定义变量 存储数据let selectItem = 0; //存储选中商品的数量let selectTotalNum = 0; //存储选中商品的总数量let totalPrice = 0; //存储选中商品的总价格// 找到选中的商品cartList.forEach(function (item) {if (item.status == true) {selectItem++;selectTotalNum += item.number;totalPrice += item.price * item.number;}})// 查找数据 渲染页面// 选中的商品数量 如果代表商品总量 代表所有商品被选中var str = `<input type="checkbox" class="checkAll" ${selectItem === cartList.length ? "checked" : ""}> 全选`;cartList.forEach(function (item) {str += `
  • <input type="checkbox" class="checkOther" data-id="${item.id}"${item.status ? "checked" : ""}><img class="aligncenter" src="https://img.maxssl.com/uploads/?url=${item.pic}" alt="">${item.name}${item.price.toFixed(2)}<button class="reduce-btn"data-id="${item.id}">-<input type="text" value="${item.number}"><button class="increase-btn" data-id="${item.id}">+¥ ${(item.number * item.price).toFixed(2)}<button class="del" data-id="${item.id}">删除
`
;})str += `总件数 : ${selectTotalNum}<button class="payment" data-totalPrice="${totalPrice}"">去结算总价格 : ¥ ${totalPrice.toFixed(2)}`;oContent.innerHTML = str;// 将数据存储到localStorage中 便于下次进入可以获取上一次的数据window.localStorage.cartList = JSON.stringify(cartList);// window.localStorage.setItem("cartList", JSON.stringify(cartList));}// 调用函数 渲染页面(页面首次打开页面)myPage()// 3. 购物车的功能实现// 利用事件冒泡 把事件委托给统一的父级oContent.addEventListener('click', function (e) {// 全选效果if (e.target.className === 'checkAll') {cartList.forEach(function (item) {console.log(e.target.checked);item.status = e.target.checked;})// 渲染页面myPage()}// 清空购物车if (e.target.className === 'clearShopCart') {var warn = confirm('您确定要清空购物车吗')if (warn) {//购物车的数据为空cartList = [];// 渲染页面myPage()}}// 结算(将选择的商品总价计算打印到控制台)if (e.target.className === 'payment') {// console.log(e.target.dataset.totalprice);var price = e.target.dataset.totalprice;price = Math.round(price)confirm(`总价格为:${price}`)}// 删除所有已选中(没有选中时 禁止执行)if (e.target.className === 'delCheck') {var warn = confirm('您确定要删除当前选择的吗')if (!warn) return;// 过滤数组 只留下选中状态为falsecartList = cartList.filter(function (item) {return !item.status})// 渲染页面myPage()}// 减少商品的数量if (e.target.className === 'reduce-btn') {// 减少商品数量 不能为0cartList.forEach(function (item) {// 通过商品的ID找到点击的是哪一个商品 累减操作if (item.id == e.target.dataset.id && item.number >= 2) item.number--;})// 渲染页面myPage();}// 增加商品的数量if (e.target.className === 'increase-btn') {cartList.forEach(function (item) {// 通过商品的ID找到点击的是哪一个商品 累加操作if (item.id == e.target.dataset.id && item.number < item.total) item.number++;})// 渲染页面myPage();}// 选中商品if (e.target.className === 'checkOther') {// 遍历数组找到要修改的商品cartList.forEach(function (item) {if (item.id == e.target.dataset.id) {// 修改商品的选中状态item.status = !item.status;}})// 渲染页面myPage()}// 删除某一项商品if (e.target.className === 'del') {var warn = confirm('您确定要删除当前的商品吗');if(!warn) return;// 遍历数组 找到需要删除的项 将其过滤cartList = cartList.filter(function(item){return item.id != e.target.dataset.id;})// 渲染页面myPage()}})