【学习笔记46】JavaScript购物车的实现

一、案例效果

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?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,
    },
];


// 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 = `
        <div class="top">
			<input type="checkbox" class="checkAll" ${selectItem === cartList.length ? "checked" : ""}> 全选
		</div>
    `;

    cartList.forEach(function (item) {
        str += `
        <ul>
            <li>
                <div class="status">
                    <input type="checkbox" class="checkOther" data-id="${item.id}"  ${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="reduce-btn"  data-id="${item.id}">-</button>
                    <input type="text" value="${item.number}">
                    <button class="increase-btn" data-id="${item.id}">+</button>
                </div>
                <div class="sub">¥ ${(item.number * item.price).toFixed(2)}</div>
                <div class="destroy">
                    <button class="del" data-id="${item.id}">删除</button>
                </div>
            </li>
        </ul>
    `;
    })

    str += `
		<div class="bottom">
        <div class="totalNum">总件数 : ${selectTotalNum}</div>
        <div class="btns">
            <button class="clearShopCart">清空购物车</button>
            <button class="payment" data-totalPrice="${totalPrice}"">去结算</button>
            <button class="delCheck">删除所有已选中</button>
        </div>
        <div class="totalPrice">
            总价格 : ¥ <span>${totalPrice.toFixed(2)}</span>
        </div>
    </div>
    `;
    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;
        // 过滤数组 只留下选中状态为false
        cartList = cartList.filter(function (item) {
            return !item.status
        })

        // 渲染页面
        myPage()
    }

    // 减少商品的数量
    if (e.target.className === 'reduce-btn') {
        // 减少商品数量 不能为0
        cartList.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()
    }
})
  • 15
    点赞
  • 135
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值