JS——JS案例分享之购物车相关功能的实现

32 篇文章 2 订阅
12 篇文章 0 订阅

文章目录

 


一、示例图

 功能陈述:

  • 将商品加入购物车功能
  • 商品的删除
  • 商品数量的增加以及减少
  • 商品的全选与反全选
  • 统计当前被选中商品的数量与价格
  • 清空购物车

二、实现步骤

1.HTML结构

  <!-- 外部容器 -->
    <div class="wrap">
        <!-- 顶部容器 -->
        <div class="inner">
            <!-- 商品名称顶部区域 -->
            <div class="shop-title">
                <span class="name">商品名称 :</span><input type="text" id="goods-name"><span class="price">商品价格
                    :</span><input type="text" id="goods-price"><button id="add-shopcar">加入购物车</button>
            </div>
            <!-- 商品全选区域 -->
            <div class="shop-middle">
                <div class="shop-inner">
                    <div>
                        <input type="checkbox"
                            id="total-check"><span>全选按钮</span><span>商品名称</span><span>商品价格</span><span>数量</span><span>操作</span>
                    </div>
                    <ul id="shop-list">
                    </ul>
                </div>
            </div>
            <!-- 商品价格合计区域 -->
            <div class="shop-total">
                <span>总共<i class="shop-count">0</i>件商品,共计<i class="total-price">0</i>元<a href="javascript:;"
                        id="clear-shopcar"> 清空购物车</a></span>
            </div>
        </div>
    </div>

2.CSS样式

#body {
    background-color: #f4f4f4;
}

li {
    list-style: none;
}

/* 外部容器样式设置 */
.wrap {
    width: 1000px;
    background-image: url(../IMG/689334441.jpg);
    background-size: cover;
    background-repeat: no-repeat;
    margin: 100px auto;
    overflow: hidden;
    border-radius: 8px;
}

.inner {
    width: 950px;
    /* background-color: #EA4335; */
    margin: 25px;
}

/* 商品名称顶部区域样式设置 */
.shop-title {
    width: 100%;
    height: 70px;
    line-height: 70px;
    background-color: #fff;
}

.shop-title>span {
    margin: 0 15px 0 25px;
    font-size: 18px;
    color: #333;
}

.shop-title>input {
    height: 35px;
    /* 解决输入框输入汉字时,输入框的位置会上移大约一个像素的问题 */
    vertical-align: middle;
    width: 200px;
    outline: none;
    border: 1px solid #666;
    padding-left: 10px;
    font-size: 18px;
}

.shop-title>button {
    width: 150px;
    height: 40px;
    margin-left: 20px;
    font-size: 18px;
    color: #333;
}

/* 商品全选区域样式设置*/
.shop-middle {
    width: 100%;
    margin: 30px 0 30px 0;
}

.shop-inner {
    padding: 10px;
    background-color: #fff;
}

.shop-inner>div {
    border-bottom: 1px solid #333;
}

.shop-inner>div>span {
    height: 40px;
    line-height: 40px;
    font-size: 18px;
    display: inline-flex;
    width: 18%;
}

.shop-inner>div>#total-check {
    margin-left: 23px;
}

#shop-list>li {
    padding: 20px;
    height: 40px;
    line-height: 40px;
    font-size: 18px;
    border-bottom: 1px solid #333;
}

#shop-list>li>span {
    display: inline-flex;
    width: 18%;
}

#del {
    padding-left: 16px;
    color: #333;
}

#del:hover {
    color: rgb(0, 0, 238);
    cursor: pointer;
}

#total-check {
    margin-right: 50px;
}

#goods {
    margin-right: 220px;
}

#goods-count {
    width: 60px;
    height: 25px;
    text-align: center;
    outline: none;
    border: 1px solid #666;
}

.shop-inner i {
    display: inline-block;
    width: 15px;
    height: 20px;
    line-height: 20px;
    text-align: center;
    margin: 0 5px;
    margin-top: 5px;
    border-bottom: 1px solid #666;
    /* background-color: #bfa; */
}


/* 商品价格合计区域样式设置 */
.shop-total {
    width: 100%;
    height: 70px;
    line-height: 70px;
    background-color: #fff;
}

.shop-total>span {
    margin-left: 20px;
    font-size: 18px;
    color: #333;
}

.shop-count {
    color: black !important;
    margin: 0 5px;
    color: red !important;
}

.total-price {
    margin: 0 5px;
    color: red !important;
}

#clear-shopcar {
    margin-left: 5px;
    color: #333;
}

#clear-shopcar:hover {
    color: red !important;
}

3. JS 行为

/ 声明商品类
class Cart {
  //确定数据格式
  // 模拟数据
  goodsList = [
    { id: 1, title: "手机", price: 100, num: 1, checked: false },
    { id: 2, title: "平板", price: 500, num: 1, checked: false },
    { id: 3, title: "耳机", price: 200, num: 1, checked: false },
  ];
  
  // 获取商品列表ul
  List = document.getElementById("shop-list");
  li = this.List.children;

  // 获取商品名称输入框
  GoodsName = document.getElementById("goods-name");
  //   获取商品价格输入框
  Goodsprice = document.getElementById("goods-price");
  // 获取加入购物车按钮
  AddShopCar = document.getElementById("add-shopcar");
  //   获取全选按钮
  TotalCheck = document.getElementById("total-check");

  // 获取显示共有多少件商品的元素
  ShopCount = document.querySelector(".shop-count");
  // 获取显示商品共计多少元的元素
  TotalPrice = document.querySelector(".total-price");
  // 获取清空购物车按钮
  ClearShopcar = document.querySelector("#clear-shopcar");

  // 在 Cart类中声明一个方法用于渲染数据
  render() {
    // 声明变量用于字符串拼接以便于页面渲染
    var str = "";
    // 声明变量用于表示选中商品的总件数
    var Number = 0;
    // 声明变量用于表示选中商品的总价格
    var Tprice = 0;
    for (let i = 0; i < this.goodsList.length; i++) {
      str = str + "<li id=" + this.goodsList[i].id + ">";
      str =
        str +
        '<input type="checkbox" id="goods" ' +
        (this.goodsList[i].checked ? "checked" : "") +
        '><span id="goods-name">' +
        this.goodsList[i].title +
        '</span><span id="goods-price">' +
        this.goodsList[i].price +
        "   元" +
        "</span>";
      str =
        str +
        '<span><i class="minus">-</i><input type="text" id="goods-count" value="' +
        this.goodsList[i].num +
        '" >';
      str =
        str +
        '<i class="add">+</i></span><span><a href="javascript:;" id="del">删除</a></span>';
      str = str + "</li>";

      /*
       通过判断当前子列表的选中状态是否为选中状态,
       若是选中状态则将选中状态的 价格 与 数量  渲染到到相对应的标签上
       */
      if (this.goodsList[i].checked) {
        Number++;
        Tprice += this.goodsList[i].price * this.goodsList[i].num;
      }
    }
    // 将每一个li 的样式渲染到页面中
    this.List.innerHTML = str;
    // 将商品的件数及时渲染到页面中
    this.ShopCount.innerText = Number;
    // 将商品的总共价格及时渲染到页面中
    this.TotalPrice.innerText = Tprice;
    // 将本地数据保存到本地存储中
    localStorage.setItem ('shopdata',this.goodsList);
  }

  // 封装一个函数用于监听事件
  addEvent() {
    // this交出去给里面的事件函数调用
    var _this = this;

    // 为加入购物车按钮添加单击事件
    this.AddShopCar.addEventListener(
      "click",
      function () {
        var regexp = /^[0-9]$/g;
        if (
          _this.GoodsName.value != "" &&
          _this.Goodsprice.value != "" &&
          regexp.test(_this.Goodsprice.value)
        ) {
          _this.addGoods();
        } else {
          alert("不可添加空商品信息或不可输入非法字符!");
        }
      },
      false
    );
    // 为全选按钮添加点击事件
    this.TotalCheck.addEventListener(
      "click",
      function () {
        for (var i = 0; i < _this.goodsList.length; i++) {
          _this.goodsList[i].checked = this.checked;
        }
        // 再次渲染页面
        _this.render();
      },
      false
    );

    /*
    通过改变子列表复选框的选中状态改变全选按钮复选框选中状态
    和删除按钮的原理类似,也是通过获取当前数据记录的id
    然后将其及记录的checked属性更改即可
     */
    this.List.addEventListener("click", function (event) {
          if (event.target.nodeName == "INPUT") {
            var ID = event.target.parentNode.id;
            for (var b = 0; b < _this.goodsList.length; b++) {
              if (ID == _this.goodsList[b].id) {
                if (_this.goodsList[b].checked == false) {
                  _this.goodsList[b].checked = true;
                } else {
                  _this.goodsList[b].checked = false;
                }
              }
            }
            _this.changeChecked();
            // 再次渲染页面
            _this.render();
          }
      },
      false
    );

    // 为增加商品数量按钮添加单击事件
    this.List.addEventListener(
      "click",
      function (event) {
        if (event.target.nodeName == "I" && event.target.className == "add") {
          var idAgain = event.target.parentNode.parentNode.id;
          for (var c = 0; c < _this.goodsList.length; c++) {
            if (idAgain == _this.goodsList[c].id) {
              _this.goodsList[c].num++;
            }
          }
          // 再次渲染页面
          _this.render();
        }
      },
      false
    );
    // 为减少商品数量按钮添加单击事件
    this.List.addEventListener(
      "click",
      function (event) {
        if (event.target.nodeName == "I" && event.target.className == "minus") {
          var idOnceAagin = event.target.parentNode.parentNode.id;
          for (var d = 0; d < _this.goodsList.length; d++) {
            if (idOnceAagin == _this.goodsList[d].id) {
              if (_this.goodsList[d].num > 0) {
                _this.goodsList[d].num--;
              } else {
                _this.goodsList[d].num = 0;
              }
            }
          }
          // 再次渲染页面
          _this.render();
        }
      },
      false
    );
    /*
    实现思路——
    给当前事件对象(删除按钮)父元素通过事件委派的方式添加单击事件,
    在起初给当前父元素设置 id 属性,也就是当前商品信息的id属性,
    当点击删除按钮时,通过遍历 商品信息列表找到
    和当前父元素id属性相同的记录,通过splice删除即可
     */
    this.List.addEventListener(
      "click",
      function (event) {
        if (event.target.nodeName == "A") {
          let fatherId = event.target.parentNode.parentNode.id;
          for (var j = 0; j < _this.goodsList.length; j++) {
            if (fatherId == _this.goodsList[j].id) {
              _this.goodsList.splice(j, 1);
            }
          }
          // 实现当全选按钮选中时,若当前商品子列表的记录均被删除时全选按钮的状态随之改变
          if (_this.goodsList.length == 0) {
            _this.TotalCheck.checked = false;
          }
          // 再次渲染数据
          _this.render();
        }
      },
      false
    );

    //为清空购物车绑定单击事件
    this.ClearShopcar.addEventListener(
      "click",
      function () {
        for (var f = 0; f < _this.goodsList.length; f++) {
          _this.goodsList.splice(f);
        }
        // 再次渲染页面
        _this.render();
        // 全选按钮的状态也变为 false
        _this.TotalCheck.checked = false;
      },
      false
    );
  }

  // 封装通过改变子列表复选框的选中状态改变全选按钮复选框选中状态的函数
  changeChecked() {
    var flag = true;
    for (var a = 0; a < this.goodsList.length; a++) {
      if (this.goodsList[a].checked == false) {
        flag = false;
        break;
      }
    }
    this.TotalCheck.checked = flag;
  }

  //  封装点击按钮添加商品记录函数
  addGoods() {
    // 利用时间戳和随机函数生成一个id
    let date = new Date().getTime();
    var id = date + Math.ceil(Math.random() * 10);
    let object = {};
    object.id = id;
    object.title = this.GoodsName.value;
    object.price = this.Goodsprice.value;
    object.num = 1;
    object.checked = false;
    // console.log(object);
    this.goodsList.unshift(object);
    // 再次渲染数据
    this.render();
    this.GoodsName.value = "";
    this.Goodsprice.value = "";
  }
}

// 声明一个类的实例
var c1 = new Cart();
// console.log(c1.goodsList);
c1.addEvent();
// 调用渲染数据
c1.render();

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值