前端学习项目之—原生JS实现京东购物车(转载基础上实现删除功能)

最终效果

 

一、HTML部分

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>京东购物车</title>
    <link rel="stylesheet" href="/css/style.css">
</head>

<body>
     <!-- 项目 -->
    <div class="container">
        <div class="header">
            <div class="select">
                <input type="checkbox" class="selectall"> 全选
            </div>
            <span>商品</span>
            <span></span>
            <span>单价</span>
            <span>数量</span>
            <span>小计</span>
            <span>操作</span>
        </div>
        <!-- 店铺 -->
        <div class="wrapper">
            <div class="shop-wrap">
                <input type="checkbox" class="shopname">
                <strong>魅嫂青音专卖店</strong>
            </div>
            <div class="product">
                <ul>
                    <li class="list">
                        <input type="checkbox" class="selectlist">
                        <img src="./img/s1.jpg" alt="">
                        <p class="title">结婚礼物团扇结婚 结婚用品 女方手捧花结婚结婚扇子中式团扇秀禾服新娘结</p>
                        <p class="kind">红色双圈-双飞燕(成品单扇子)</p>
                        <p class="singleprice">¥248.40</p>
                        <div class="number">
                            <button class="reduce">-</button>
                            <input type="text" class="count" value="4">
                            <button class="addnum">+</button>
                        </div>
                        <p class="countprice">¥993.60</p>
                        <p class="control">
                            <span class="deletion">删除</span>
                            <br>
                            <span>移入关注</span>
                        </p>
                    </li>
                    <li class="list">
                        <input type="checkbox" class="selectlist">
                        <img src="./img/s2.jpg" alt="">
                        <p class="title">结婚礼物团扇结婚 结婚用品 女方手捧花结婚结婚扇子中式团扇秀禾服新娘结</p>
                        <p class="kind">红色双圈-双飞燕(成品单扇子)</p>
                        <p class="singleprice">¥194.40</p>
                        <div class="number">
                            <button class="reduce disabled">-</button>
                            <input type="text" class="count" value="1">
                            <button class="addnum">+</button>
                        </div>
                        <p class="countprice">¥194.40</p>
                        <p class="control">
                            <span class="deletion">删除</span>
                            <br>
                            <span>移入关注</span>
                        </p>
                    </li>
                </ul>
            </div>
        </div>
        <div class="wrapper">
            <div class="shop-wrap">
                <input type="checkbox" class="shopname">
                <strong>礼尚往来礼品专营店</strong>
            </div>
            <div class="product">
                <ul>
                    <li class="list">
                        <input type="checkbox" class="selectlist">
                        <img src="./img/s3.jpg" alt="">
                        <p class="title">结婚礼物团扇结婚 结婚用品 女方手捧花结婚结婚扇子中式团扇秀禾服新娘结</p>
                        <p class="kind">红色双圈-双飞燕(成品单扇子)</p>
                        <p class="singleprice">¥119.00</p>
                        <div class="number">
                            <button class="reduce disabled">-</button>
                            <input type="text" class="count" value="1">
                            <button class="addnum">+</button>
                        </div>
                        <p class="countprice">¥119.00</p>
                        <p class="control">
                            <span class="deletion">删除</span>
                            <br>
                            <span>移入关注</span>
                        </p>
                    </li>
                    <li class="list">
                        <input type="checkbox" class="selectlist">
                        <img src="./img/s4.jpg" alt="">
                        <p class="title">结婚礼物团扇结婚 结婚用品 女方手捧花结婚结婚扇子中式团扇秀禾服新娘结</p>
                        <p class="kind">红色双圈-双飞燕(成品单扇子)</p>
                        <p class="singleprice">¥119.00</p>
                        <div class="number">
                            <button class="reduce">-</button>
                            <input type="text" class="count" value="2">
                            <button class="addnum">+</button>
                        </div>
                        <p class="countprice">¥238.00</p>
                        <p class="control">
                            <span class="deletion">删除</span>
                            <br>
                            <span>移入关注</span>
                        </p>
                    </li>
                </ul>
            </div>
        </div>
        <div class="wrapper">
            <div class="shop-wrap">
                <input type="checkbox" class="shopname">
                <strong>智慧礼品官方旗舰店</strong>
            </div>
            <div class="product">
                <ul>
                    <li class="list">
                        <input type="checkbox" class="selectlist">
                        <img src="./img/s5.jpg" alt="">
                        <p class="title">结婚礼物团扇结婚 结婚用品 女方手捧花结婚结婚扇子中式团扇秀禾服新娘结</p>
                        <p class="kind">红色双圈-双飞燕(成品单扇子)</p>
                        <p class="singleprice">¥188.00</p>
                        <div class="number">
                            <button class="reduce disabled">-</button>
                            <input type="text" class="count" value="1">
                            <button class="addnum">+</button>
                        </div>
                        <p class="countprice">¥188.00</p>
                        <p class="control">
                            <span class="deletion">删除</span>
                            <br>
                            <span>移入关注</span>
                        </p>
                    </li>
                </ul>
            </div>
        </div>
    </div>
    <div class="combine">
        <p>
            已选择
            <em class="amount-sum">0</em>
            件商品
        </p>
        <p>
            总价
            <span class="pricetotal priceShow">&yen;0.00</span>
        </p>
    </div>
    <script src="./js/main.js"></script>
</body>

</html>

二、CSS部分


/* 格式化*/
* {
    margin: 0;
    padding: 0;
}

/* 设置img右行盒inline到块盒block*/
img {
    display: block;
}
/* 设置列表样式为无样式 */
ul,li {
    list-style: none;
}

/* css 添加手状样式,鼠标移上去变小手 */
input {
    cursor: pointer;
}

/* css 添加手状样式,鼠标移上去变小手 */
button{
    cursor: pointer;
}

/* css 添加手状样式,鼠标移上去变小手 */
.control{
    cursor: pointer;
}

.container {
    width: 990px;
    font-size: 12px;
    color: #434343;
    margin: 0 auto;
}

.header {
    display: flex; /* 设置header为弹性盒子 */
    height: 40px;
    padding: 5px 0;
    line-height: 40px;      /* line-height,又称行高,指的是两行文字基线之间的距离 */
    margin-bottom: 10px;
}

.select {
    width: 133px;
}

/* 对第三个span的设置 */
.header span:nth-child(2) { 
    width: 208px;
}

.header span:nth-child(3) {
    width: 170px;
    padding: 0 10px 0 20px;
}

/* text-align用来设置元素中的的文本对齐方式 */
.header span:nth-child(4) {
    width: 170px;
    padding-right: 50px;
    text-align: right; 
}

.header span:nth-child(5) {
    width: 80px;
    text-align: center;
}

.header span:nth-child(6) {
    width: 140px;
    padding-right: 40px;
    text-align: right;
}

.header span:nth-child(7) {
    width: 75px;
}

.shop-wrap {
    height: 30px;
    line-height: 30px;
    padding-left: 11px;
    margin-bottom: 10px;
    border-bottom: 2px solid #aaa;
}

/* 默认 flex-direction: row ;,加上align-items: flex-start; 以为着横行交叉轴的起始位置*/
.list {
    display: flex;
    align-items: flex-start; 
    margin-bottom: 10px;
    height: 108px;
}

.selectlist {
    margin-right: 20px;
}

.list img {
    width: 80px;
    height: 80px;
    margin-right: 10px;
}

/* 给一个元素中设置overflow:hidden,那么该元素的内容若超出
了给定的宽度和高度属性,那么超出的部分将会被隐藏,不占位。 */
.list .title {
    font-size: 12px;
    width: 204px;
    height: 40px;
    line-height: 20px;
    overflow: hidden;

}

/* 用于设置文本在容器中溢出时的显示方式。当值设置为 ellipsis 时,
文本会以省略号 (...) 的形式来代替被隐藏的文本部分 */
.kind {
    width: 160px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap; /* 用于指定元素内的文本不换行 */
    font-size: 12px;
}

.singleprice {
    text-align: right;
    width: 190px;
    padding-right: 40px;
}

.number {
    width: 84px;
    display: flex;
    justify-content: flex-start;  /* 在主轴上由左向右排列  */
}

.number button {
    width: 17px;
    height: 22px;
    background-color: #fff;
    border: 1px solid #aaa;
}

.count {
    width: 46px;
    height: 20px;
    outline: none;
    border: 1px solid #aaa;
    text-align: center;
}

.countprice {
    width: 140px;
    padding-right: 40px;
    text-align: right;
    font-weight: 900;
}

.control {
    width: 75px;
    text-align: left;
}

.disabled {
    cursor: no-drop; /* 不可拖动光标 */
}

.combine {
    width: 990px;
    height: 30px;
    line-height: 30px;
    margin: 0 auto; /* 水平居中 */
    display: flex;
    font-size: 12px;
    color: #434343;
    justify-content: flex-start;
}

.amount-sum {
    color: #e2231a;
    font-style: normal;
    font-weight: 900;
}

.combine p {
    margin-right: 20px;
}

.pricetotal {
    font-size: 16px;
    font-weight: 900;
    color: #e2231a;
}

三、JS部分

在转载的基础上加入了对删除按钮的操作

​​​​​​​

let selectall = document.querySelector('.selectall');
//  查找所有的店铺
let shopname = document.querySelectorAll('.shopname');
// 查找所有的商品列表
let selectlist = document.querySelectorAll('.selectlist');

//  查找所有的操作数量按钮
let addnum = document.querySelectorAll('.addnum'); //加
let reduce = document.querySelectorAll('.reduce'); //减
let count = document.querySelectorAll('.count'); //计数

//  获取删除节点
let deletion = document.querySelectorAll('.deletion');

//  获取 单一商品的价钱 小计 
let countprice = document.querySelectorAll('.countprice');
//  获取 每个商品的单价
let singleprice = document.querySelectorAll('.singleprice');
//  获取 总件数  总价钱
let amount_sum = document.querySelector('.amount-sum');
let pricetotal = document.querySelector('.pricetotal')

//  实现全选的效果
selectall.onclick = function () {
    // 获取全选按钮的状态
    let status = this.checked;
    // 将全选按钮状态同步到每个店铺
    shopname.forEach(function (item, index) {
        item.checked = status;
    })
    // 将全选按钮状态同步到每个商品
    selectlist.forEach(function (item, index) {
        item.checked = status;
    })
    //  计算总价和总数
    countTotal(count,selectlist)
}

//  点击 加号 改变 商品数量
addnum.forEach(function (item, index) {
    item.onclick = function () {
        // 获取当前点击的节点所在数量,通过index确定具体是点击那个
        let val = +count[index].value;
        // 点击一次调用一次,数量加一
        val++;
        // 将最终的数量赋值给count所在节点的value   
        count[index].value = val;
        // 因为value初始值最小为1,增加数量的时候去掉不能点击限制
        reduce[index].classList.remove('disabled');
        // 计算小计
        countSinglePrice(index, val);
        // 获取店铺所有商品节点列表HTMLCollection(2) [li.list, li.list]
        let shop_all_product = this.parentElement.parentElement.parentElement.children;
        // 获取店铺名所在节点 <input type="checkbox" class="shopname">
        let shop_parent = this.parentElement.parentElement.parentElement.parentElement.previousElementSibling.children[0];
        // 点击增加数量默认商品变为选择态,同时判断店铺是否为选择态
        selectShopName(shop_all_product, shop_parent);
        // 判断全选是否变为选择态
        selectAllButton();
        // 计算选择数量和总价
        countTotal(count,selectlist)
    }
})

//  点击 减号 改变 商品数量
reduce.forEach(function (item, index) {
    item.onclick = function () {
        //  + 实现隐式类型转换string变number,也可用number函数转换
        // 获取当前点击的节点所在数量,通过index确定具体是点击那个
        let val = +count[index].value;
        // 数量最小为1
        if (val == 1) {
            val = 1;
        // 数量不是1,随着点击减少
        } else {
            val--;
        }
        // 如果小于1,增加disabled属性,变为不可选状态,此处通过多类名实现
        if (val <= 1) {
            this.classList.add('disabled')
        }
        // 将最终的数量赋值给count所在节点的value 
        count[index].value = val;
        // 计算小计
        countSinglePrice(index, val);
        // 获取店铺所有商品节点列表HTMLCollection(2) [li.list, li.list]
        let shop_all_product = this.parentElement.parentElement.parentElement.children;
        // 获取店铺名所在节点 <input type="checkbox" class="shopname">
        let shop_parent = this.parentElement.parentElement.parentElement.parentElement.previousElementSibling.children[0]
        // 点击删除数量默认商品变为选择态,同时判断店铺是否为选择态
        selectShopName(shop_all_product, shop_parent);
        // 判断全选是否变为选择态
        selectAllButton();
        // 计算选择数量和总价
        countTotal(count,selectlist)
    }
})

// 实现删除效果
deletion.forEach(function(item,index){
    item.onclick = function(){
        // 获取店铺商品列表节点
        const shop_list_product = this.parentElement.parentElement.parentElement;
        console.log(shop_list_product)
        // 获取商品节点
        const shop_product = this.parentElement.parentElement;
        // 暂存店铺商品列表的原始长度     
        // 获取店铺的所有商品节点,shop_list_product.children结果为HTMLCollection(2) [li.list, li.list],数组里面的内容是对象
        const shop_lenth = shop_list_product.children.length;
        // 获取店铺父节点
        const shop_wrapper = this.parentElement.parentElement.parentElement.parentElement.previousElementSibling.parentElement
        // 获取店铺节点
        const ship_wrap = this.parentElement.parentElement.parentElement.parentElement.previousElementSibling
        // 删除商品
        shop_list_product.removeChild(shop_product);

        // 如果店铺商品列表的原始长度等于1,说明此次删除操作完再没有商品,同时删除店铺列表
        if(shop_lenth == 1){
            shop_wrapper.removeChild(ship_wrap)
        }
        // 更新商品选择列表
        let selectlist_update = document.querySelectorAll('.selectlist');
        // 更新商品计数列表
        let count_update = document.querySelectorAll('.count');
        // 计算选择数量和总价
        countTotal(count_update, selectlist_update);

    }
})

//  选择店铺  实现选中该店铺所有的商品
shopname.forEach(function (item, index) {
    item.onclick = function () {
        let shop_status = this.checked; //获取当前店铺的选取状态
        // 获取店铺商品列表HTMLCollection(2) [li.list, li.list]
        let product_list = this.parentElement.nextElementSibling.children[0].children;
        // 让商品的选择状态和店铺的选择状态保持一致
        for (let i = 0; i < product_list.length; i++) {
            product_list[i].children[0].checked = shop_status
        }

        // 选择所有店铺,全选按钮改变选择状态
        let shop_number = 0;
        // 每次选择一个店铺的时候对所有店铺的选择状态做遍历
        shopname.forEach(function (item_status, index) { 
            if (item_status.checked) { 
                shop_number += 1; // 如果是选择态shop_number加1
            }
        })

        // 如果所有店铺都是选择态,全选按钮全选
        if (shopname.length == shop_number) {
            selectall.checked = true;
        } else {
            selectall.checked = false;
        }
        countTotal(count,selectlist)
    }
})

//  选择商品 实现店铺选中的效果  函数封装 
//  参数 ele: 店铺下的所有的商品   ; shop_parent 店铺名所在节点<input type="checkbox" class="shopname">
function selectShopName(ele, shop_parent) {
    let list_number = 0;
    for (let i = 0; i < ele.length; i++) {
        if (ele[i].children[0].checked) {
            list_number++;
        }
    }

    if (list_number == ele.length) {
        shop_parent.checked = true;
    } else {
        shop_parent.checked = false;
    }
}

//  选择单一商品 实现店铺的选中 和 全选按钮的选中 
selectlist.forEach(function (item, index) {
    item.onclick = function () {
        // 店铺下的所有的商品 HTMLCollection(2) [li.list, li.list]
        let shop_all_product = this.parentElement.parentElement.children;
        // 店铺名所在节点<input type="checkbox" class="shopname">
        let shop_parent = this.parentElement.parentElement.parentElement.previousElementSibling.children[0];
        console.log(shop_parent)
        selectShopName(shop_all_product, shop_parent);
        selectAllButton();
        countTotal(count,selectlist)
    }
})

//  实现单一商品的价钱计算
function countSinglePrice(index, val) {
    let s_price = Number(singleprice[index].innerHTML.substring(1))
    let single_count_price = (s_price * val).toFixed(2);
    countprice[index].innerHTML = `&yen; ${single_count_price}`;
    //  默认选中该商品
    selectlist[index].checked = true;
}

//  选中所有单一商品 实现全选按钮选中
function selectAllButton() {
    let single_product = 0;
    selectlist.forEach(function (single_status, index) {
        if (single_status.checked) { //检查每一个商品的选择状态
            single_product++
        }
    })
    if (single_product == selectlist.length) {
        selectall.checked = true;
    } else {
        selectall.checked = false;
    }
}


// 删除后实现商品总价钱和 总数量的计算
// coun:所有商品数量   sele:所有商品的选择节点
function countTotal(coun, sele) {
    let countTotalNumber = 0; // 选中的商品的总数量
    let countTotalPrice = 0; // 选中是商品的总价钱
    coun.forEach(function (item, index) {
        if (sele[index].checked) {
            //  计算商品数量
            let num = +item.value;
            countTotalNumber += num;
            //  计算总价钱
            let single_price = Number(countprice[index].innerHTML.substring(1));
            countTotalPrice += single_price;
        }
    })
    amount_sum.innerHTML = countTotalNumber;
    pricetotal.innerHTML = `&yen;${countTotalPrice}`;
}
  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
由于京东购物车页面是动态生成的,代码比较复杂,以下是其中一部分JS代码示例: ```javascript // 加入购物车 function addToCart(pid, num) { $.ajax({ url: '/cart/addToCart.action', type: 'post', data: { "pid": pid, "pcount": num }, dataType: 'json', success: function (data) { if (data.resultCode == 0) { // 添加成功 alert('添加成功'); } else if (data.resultCode == 1) { // 添加失败 alert('添加失败'); } else if (data.resultCode == 2) { // 未登录 alert('请先登录'); } }, error: function () { alert('系统繁忙,请稍后再试'); } }); } // 修改商品数量 function updateProductNum(pid, num) { $.ajax({ url: '/cart/updateProductNum.action', type: 'post', data: { "pid": pid, "pcount": num }, dataType: 'json', success: function (data) { if (data.resultCode == 0) { // 修改成功 alert('修改成功'); } else if (data.resultCode == 1) { // 修改失败 alert('修改失败'); } else if (data.resultCode == 2) { // 未登录 alert('请先登录'); } }, error: function () { alert('系统繁忙,请稍后再试'); } }); } // 删除商品 function deleteProduct(pid) { $.ajax({ url: '/cart/deleteProduct.action', type: 'post', data: { "pid": pid }, dataType: 'json', success: function (data) { if (data.resultCode == 0) { // 删除成功 alert('删除成功'); } else if (data.resultCode == 1) { // 删除失败 alert('删除失败'); } else if (data.resultCode == 2) { // 未登录 alert('请先登录'); } }, error: function () { alert('系统繁忙,请稍后再试'); } }); } ``` 以上代码是一部分JS代码示例,主要实现了添加商品到购物车、修改商品数量和删除商品等功能。这些功能都是通过Ajax技术实现的,与后台进行交互,返回相应的结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值