购物车小案例

273 阅读5分钟

购物车

360截图17571119101101122.jpg 效果说明:

  1. 选中全选 下面的选择框会跟着选中 ,全选取消,下面的选择框也会跟着取消,在选中或者未选中时,总件数,总价格会随之变化,
    
  2. 点击加号按钮,商品数量会增加,当达到库存量时,加号按钮禁用,点击减号按钮商品数量会减少,当数量为1时,减号按钮禁用,点击过程中,总件数,总价格会随之变化,
    
  3. 点击删除按钮,该行数据会被删除
    
  4. 点击清空购物车,全部数据被删除
    
  5. 点击结算,将总价格打印在后台
    
  6. 点击删除所有选中,选中的数据将被删除
    
  7. 在操作各功能的的时候,总件数、总价格都会发生变化
    
  8. 最后将操作数据存储在本地
    

html 结构

	<div class="header">页面顶部</div>
	<div class="content">
		<!-- JS渲染 -->
		<!-- <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>

	<!-- 引入js -->
	<script src="./购物车.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;
}

分析

数组数据分析

    {
        id: 111234,
        status: false,
        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,
    }
  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 本地存储
// 再次打开可以得到的数为 原来的数据 或者 上一次操作过后的数据
var cartList = JSON.parse(window.localStorage.getItem("cartList")) || [
    // 每一个对象就是一个购物车内容的数据  JSON.parse() 将字符串转换 为数组 /  再次打开页面时 展示的是上一次操作后的页面  
    {
        id: 111234,
        status: false,
        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: false,
        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,
    },
];

js 实现

var content = document.querySelector('.content');  // 获取元素


// 定义函数 渲染页面

function fun() {  
    // 定义变量
    var selctItem = 0; // 储存商品中的数量
    var selctTotalNum = 0; // 总数
    var totalPrice = 0;  //总价

    cartList.forEach(function (item) {
        if (item.status) {
            selctItem++;  // 选中按钮未true 数量自增
            selctTotalNum += item.number;  // 总数等于全部数量相加
            totalPrice += item.price * item.number;  //总价等于总数量*总价
        }
    })

    var str = `
        <div class="top">
        <input class="quXun" type="checkbox" ${selctItem === cartList.length ? "checked" : " "}> 全选
    </div>
    <ul>`
    // ${selctItem === cartList.length ? "checked" : " "  判断数据是否等于数组长度 ,等于赋值"checked"(即选中)  不等于 为空

    // 数组遍历 将每个数组渲染到数组中
    cartList.forEach(function (item) {    //data-id="${item.id}"  将实时id赋给data-id   data-id  => h5新增属性
        str += `
        <li>
            <div class="status">
                <input class="danXun" data-id="${item.id}" 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="jing" data-id="${item.id}">-</button>
                <input type="text" value="${item.number}">
                <button class="jia" data-id="${item.id}">+</button>
            </div>.
            <div class="sub">
                ¥ ${(item.price * item.number).toFixed(2)}
            </div>
            <div class="destory">
                <button data-id="${item.id}" class="del1">删除</button>
            </div>
        </li>`
    })

    str += `
    </ul>
    <div class="bottom">
        <div class="totalNum">
            总件数 : ${selctTotalNum}
        </div>
        <div class="btns">
            <button class="clier">清空购物车</button>
            <button class="jieSun" data-totalPrice="${totalPrice.toFixed(2)}">去结算</button>
            <button class="del">删除所有已选中</button>
        </div>
        <div class="totalPrice">
            总价格 : ¥ <span>${totalPrice.toFixed(2)}</span>
        </div>
    </div>
        `
    content.innerHTML = str;  // 渲染页面
    //本地存储数据
    window.localStorage.setItem('cartList', JSON.stringify(cartList)); // 将数组转换未字符串 进行本地存储
}
fun();


content.onclick = function (e) {
    // console.log(1);
    // 全选按钮
    if (e.target.className == "quXun") {  // 找到全选按钮 点击
        // console.log(1);`
        cartList.forEach(function (item) {   // 遍历数组 拿到每一个数据
            item.status = e.target.checked;  // 使拿到 选中
        })
        fun();  //调用函数 渲染页面



    }
    // 单选按钮
    if (e.target.className == "danXun") {
        console.log(1);
        cartList.forEach(function (item) {
            if (item.id == e.target.dataset.id) {
                item.status = !item.status; // 点击时status为false 点击后就变为true  => 点击后是否被选 取决于点击前是否被选  取反
            }
        })
        fun();
    }


    // 数量减
    if (e.target.className == "jing") {  //通过判断类名  找到减去标签
        cartList.forEach(function (item) {  // 遍历数组拿到每一个数据
            // console.log(item);
            if (item.id == e.target.dataset.id && item.number >= 2) {  // 判断是否id相同  相同就可以减   减到1时按钮禁止
                item.number--; // 数量自减
            }
        })
        fun(); // 调用函数渲染页面

    }

    // 数量加
    if (e.target.className == "jia") {
        // console.log(1);
        cartList.forEach(function (item) {
            if (item.id == e.target.dataset.id && item.number < item.total) {   // 不会一直加 达到库存量后按钮禁用
                item.number++; // 数量自加
            }
        })
        fun();  // 调用函数渲染页面
    }

    //清空购物车
    if (e.target.className == "clier") {
        // console.log(1);
        var b = confirm('您确定要清空吗?');
        if (b) {
            cartList = []; // 清空后无数据  => 将数组赋值为空数组
        }
        fun();
    }

    // 去结算
    if (e.target.className == "jieSun") {
        // console.log(1);
        console.log(e.target.dataset.totalprice);  // dataset-totalPrice: h5新增自定义属性  dataset.totalprice

    }


    //删除所有已选中
    if (e.target.className == "del") {
        // console.log(1);
        var b = confirm('您确定要删除吗?');
        if (b) {
            cartList = cartList.filter(function (item) {  //数组过滤
                return !item.status;  // 选中取反  =>  选中的被过滤掉
            })
        }
        fun();

    }
    // 删除某一项 
    if(e.target.className == "del1"){
        // console.log(1)
        var b = confirm('你确定要删除吗')
        if(!b) return // 取消啥也不执行
        cartList = cartList.filter(function(item){
                return item.id != e.target.dataset.id; // 删除id相同的  同时利用h5新增属性 在点击按钮处添加动态id 
             
        })
        fun(); // 调用函数渲染
    }

}