JavaScript实现简易购物车最全代码解析(ES6面向对象)

本文实例为大家分享了JavaScript实现简易购物车的具体代码,供大家参考,具体内容如下

代码:

<!DOCTYPE html>
<html>
 <head>
  <meta charset="utf-8" />
  <title>ES6购物车</title>
  <style type="text/css">
   table {
    width: 50%;
    position: relative;
    margin: 0px auto;
    border-collapse: collapse;
    border: 1px solid gray;
    box-sizing: border-box;
   }
   th {
    background-color: coral;
    height: 2.5em;
    margin: 0 auto;
   }
   tr {
    height: 2.5em;
    margin: 0 auto;
    text-align: center;
   }
   .box {
    margin: auto;
    width: 50%;
   }
  </style>
 </head>
 <body>
  <h3 style="text-align: center;margin-top: 100px;">猜你喜欢</h3>
  <table border="1px" id="update-table">
   <tbody>
   <tr>
    <th>序号</th>
    <th>商品名称</th>
    <th>单价</th>
    <th>操作</th>
   </tr>
   <tr class="update-goods">
    <td>1</td>
    <td>肉夹馍</td>
    <td>8</td>
    <td><input type="button" class="update" value="加入购物车" /></td>
   </tr>
   <tr class="update-goods">
    <td>2</td>
    <td>擀面皮</td>
    <td>6</td>
    <td><input type="button" class="update" value="加入购物车" /></td>
   </tr>
   <tr class="update-goods">
    <td>3</td>
    <td>冰封</td>
    <td>3</td>
    <td><input type="button" class="update" value="加入购物车" /></td>
   </tr>
   <tr class="update-goods">
    <td>4</td>
    <td>羊肉泡馍</td>
    <td>25</td>
    <td><input type="button" class="update" value="加入购物车" /></td>
   </tr>
   </tbody>
  </table>
  <h3 style="text-align: center;">购物车</h3>
  <table border="1px" id="goods">
   <tbody>
    <tr>
     <th>序号</th>
     <th>商品名称</th>
     <th>数量</th>
     <th>单价</th>
     <th>小计</th>
     <th>操作</th>
    </tr>
    <tr>
     <td>1</td>
     <td>肉夹馍</td>
     <td>
      <button type="button">-</button>
      <span class="goods-num">0</span>
      <button type="button">+</button>
     </td>
     <td>
      单价:<span class="goods-price">8</span>
     </td>
     <td>
      小计:<span class="goods-single-price">0</span>
     </td>
     <td>
      <input type="button" class="deled" value="删除" />
     </td>
    </tr>
    <tr>
     <td>2</td>
     <td>擀面皮</td>
     <td>
      <button type="button">-</button>
      <span class="goods-num">0</span>
      <button type="button">+</button>
     </td>
     <td>
      单价:<span class="goods-price">6</span>
     </td>
     <td>
      小计:<span class="goods-single-price">0</span>
     </td>
     <td>
      <input type="button" class="deled" value="删除" />
     </td>
    </tr>
    <tr>
     <td colspan="5">
      一共<span id="goods-total-num">0</span>件商品,共计花费<span id="goods-total-price">0</span>元。
     </td>
    </tr>
   </tbody>
  </table>
 </body>
</html>
<script type="text/javascript">
 class Cart {
  constructor() {
   this.eventBind();
  }
  //获取并更新商品总数量
  getGoodsNumAndUpdate() {
   //获取所有商品的数量
   let oGoodsNum = document.getElementsByClassName("goods-num");
   //存放商品数量叠加的总值
   let goodsTotalNum = 0;
   //循环所有商品
   for (let i = 0; i < oGoodsNum.length; i++) {
    //将所有循环到的商品数量相加
    goodsTotalNum += Number(oGoodsNum[i].innerHTML);
   }
   //获取总结栏的商品总数
   let oGoodsTotalNum = document.getElementById("goods-total-num");
   //将循环所得商品数量之和赋给总结栏商品总数
   oGoodsTotalNum.innerHTML = goodsTotalNum;
  }
  //获取并更新总货物总价格
  getGoodsPriceAndUpdate() {
   //获取小计
   let oGoodsSinglePrice = document.getElementsByClassName("goods-single-price");
   //新创建一个元素接受小计的数值(用于最后赋值给获取小计的元素)
   let goodsTotalPrice = 0 ;
   //循环所有小计
   for (let i = 0; i < oGoodsSinglePrice.length; i++) {
    //将所有循环到的小计数量相加
    goodsTotalPrice += Number(oGoodsSinglePrice[i].innerHTML);
   }
   //获取总结栏的价格总数
   let oGoodsTotalPrice = document.getElementById("goods-total-price");
   //将循环所得小计数量之和赋给总结栏价格总数
   oGoodsTotalPrice.innerHTML = goodsTotalPrice;
  }
  //2.获取小计
  getSinglePrice(num, price) {
   //每行小计数等于单价与本行商品之积
   return num * price;
  }
  //加号按钮方法
  addGoods(btn) {
   //获取加号上一个兄弟元素(中间数值)
   let oGoodsNum = btn.previousElementSibling;
   //1.点击后数值加一
   oGoodsNum.innerHTML = Number(oGoodsNum.innerHTML) + 1;
   //获取单价(btn父元素的下一个元素的子元素)
   let oPrice = btn.parentNode.nextElementSibling.firstElementChild;
   //获取小计(btn父元素的下一个元素的下一个元素的子元素)
   let oSinglePrice = btn.parentNode.nextElementSibling.nextElementSibling.firstElementChild;
   //2.重新获取小计数值并赋给小计
   oSinglePrice.innerHTML = this.getSinglePrice(oGoodsNum.innerHTML, oPrice.innerHTML);
   //3.获取并更新商品总数量(调用重新执行>刷新数据)
   this.getGoodsNumAndUpdate();
   //4.获取并更新总货物总价格(调用重新执行>刷新数据)
   this.getGoodsPriceAndUpdate();
  }
  //减号按钮方法
  minGoods(btn) {
   //获取减号下一个兄弟元素(中间数值)
   let oGoodsNum = btn.nextElementSibling;
   //判断如果商品数量大于零
   if (oGoodsNum.innerHTML > 0) {
    //1.点击后数值减一
    oGoodsNum.innerHTML = oGoodsNum.innerHTML - 1;
    //获取单价(btn父元素的下一个元素的子元素)
    let oPrice = btn.parentNode.nextElementSibling.firstElementChild;
    //获取小计(btn父元素的下一个元素的下一个元素的子元素)
    let oSinglePrice = btn.parentNode.nextElementSibling.nextElementSibling.firstElementChild;
    //2.重新获取小计数值并赋给小计
    oSinglePrice.innerHTML = this.getSinglePrice(oGoodsNum.innerHTML, oPrice.innerHTML);
    //3.获取并更新商品总数量(调用重新执行>刷新数据)
    this.getGoodsNumAndUpdate();
    //4.获取并更新总货物总价格(调用重新执行>刷新数据)
    this.getGoodsPriceAndUpdate();
   }
  }
  //删除按钮方法
  delGoods(btn) {
   //获取购物车table元素
   let god = document.getElementById("goods");
   //获取此按钮父元素的父元素
   let oTr = btn.parentNode.parentNode;
   //然后删除此元素(在此指按钮选择的整个tr元素)
   oTr.remove();
   //重新排序号(循环名为god的table元素下的所有子元素tr)(从第二个子元素开始,并且去掉最后一个小计行)
   for (let i = 1; i < god.firstElementChild.children.length - 1; i++) {
    //将循环之后的元素数值i赋值给名为god的table元素下的子元素tr下的第一个子元素td
    god.firstElementChild.children[i].firstElementChild.innerHTML = i;
   }
   //3.获取并更新商品总数量(调用重新执行>刷新数据)
   this.getGoodsNumAndUpdate();
   //4.获取并更新总货物总价格(调用重新执行>刷新数据)
   this.getGoodsPriceAndUpdate();
  }

  //添加订单方法
  update() {
   //获取所有类名为update的元素
   let btn = document.getElementsByClassName("update");
   //获取所有id名为update-table的元素
   let updateTable = document.getElementById("update-table");
   //获取购物车table元素
   let god = document.getElementById("goods");
   //获取购物车table元素的第一个子元素tbody的所有子元素tr
   let gods = god.firstElementChild.children;
   //目标元素赋值为false
   let flag = false;
   //这个this是为了避免在事件体内cart的对象被覆盖
   let that = this;
   //循环所有类名为update的元素
   for (let i = 0; i < btn.length; i++) {
    //类名为update的点击事件
    btn[i].onclick = function() {
     //循环购物车table元素的第一个子元素tbody的所有子元素tr
     for (let j = 0; j < gods.length - 1; j++) {
      //循环判断菜单中是否有这个菜,如果有这个菜则加1;
      //本意为在购物车寻找相同名称的商品如果有则执行购物车的这条数据商品数量+1;如果没有则使flag为true跳出判断
      //this是类名为update元素input标签
      //购物车table中所有子元素tr遍历 下的第一个子元素的内容==类名为update元素input的父元素td的上一个兄弟元素的上一个兄弟元素的内容 时执行
      if (gods[j].children[1].innerHTML == this.parentNode.previousElementSibling.previousElementSibling.innerHTML) {
       //购物车table中所有子元素tr遍历 下的第二个子元素的内容(即为购物车中商品的数量)+1
       gods[j].children[2].children[1].innerHTML = " " + (Number(gods[j].children[2].children[1].innerHTML) + 1) + " ";
       //购物车table中所有子元素tr遍历 下的第四个子元素的内容(即为购物车中小计的数值被赋值)
       gods[j].children[4].innerHTML = '小计:<span class="goods-single-price">' +
       gods[j].children[2].children[1].innerHTML * gods[j].children[3].firstElementChild.innerHTML + '</span>';
       //3.获取并更新商品总数量(调用重新执行>刷新数据)
       that.getGoodsNumAndUpdate();
       //4.获取并更新总货物总价格(调用重新执行>刷新数据)
       that.getGoodsPriceAndUpdate();
       //给flag赋值为false
       flag = false;
       //跳出本次循环
       break;
      } else {
      //购物车table中所有子元素tr遍历 下的第一个子元素的内容!=类名为update元素input的父元素td的上一个兄弟元素的上一个兄弟元素的内容 时执行
      //赋值给flag为true
       flag = true;
      }
     }
     if (flag) {
      //如果没有这个菜则添加
      //创建一个节点tr
      let tr = document.createElement("tr");
      //添加这个节点的内容
      tr.innerHTML=
       '<td>'+(gods.length-1)+'</td>'+
       '<td>'+this.parentNode.previousElementSibling.previousElementSibling.innerHTML+
       '</td><td><button type="button">-</button><span class="goods-num"> 1 </span><button type="button"> +</button></td><td>单价:<span class="goods-price">' +
       this.parentNode.previousElementSibling.innerHTML +
       '</span></td><td>小计:<span class="goods-single-price">' +
       this.parentNode.previousElementSibling.innerHTML +
       '</span></td><td><input type="button" class="deled" value="删除" /></td>';
       //给tbody里添加新元素
      god.firstElementChild.insertBefore(tr, god.firstElementChild.lastElementChild);
      //触发事件按钮
      that.eventBind();
      //3.获取并更新商品总数量(调用重新执行>刷新数据)
      that.getGoodsNumAndUpdate();
      //4.获取并更新总货物总价格(调用重新执行>刷新数据)
      that.getGoodsPriceAndUpdate();
     }
    }
    //重新排猜你喜欢里的商品序号
    for (let i = 1; i < updateTable.firstElementChild.children.length; i++) {
     //排好的数值赋值给新添加的商品序号值
     updateTable.firstElementChild.children[i].firstElementChild.innerHTML = i;
    }
   }
  }
  //触发事件按钮
  eventBind() {
   //获取所有标签名为botton的按钮
   let oBtns = document.getElementsByTagName("button");
   //这个this是为了避免在事件体内cart的对象被覆盖
   let that = this;
   //循环所有botton按钮
   for (let i = 0; i < oBtns.length; i++) {
    if (i % 2) {//为奇数时触发addGoods()方法
     oBtns[i].onclick = function() {
      that.addGoods(this);
     }
    } else {//为偶数时触发minGoods()方法
     oBtns[i].onclick = function() {
      that.minGoods(this);
     }
    }
   }
   //获取所有类名为deled的元素
   let oDelBtns = document.getElementsByClassName("deled");
   //循环所有deled元素
   for (let i = 0; i < oDelBtns.length; i++) {
    //deled元素的点击事件
    oDelBtns[i].onclick = function() {
     //调用delGoods()方法执行删除效果
     that.delGoods(this);
    }
   }
   //调用添加订单
   this.update();
  }
 }
 let c = new Cart();
</script>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 关于前端JavaScript ES6详情

    目录 1.简介 1.1 Babel 转码器 1.2 polyfill 2.let 和 const 2.1 let 2.2 const 3.解构 3.1 对象解构 3.2 数组解构 3.3 函数参数解构 3.4 常见场景 4.扩展 4.1 字符串扩展 4.2 函数扩展 4.3 数组扩展 4.4 对象扩展 4.5 运算符扩展 5.for-of 6.小结 1.简介 ES6是一个泛指,含义是 5.1 版以后的 JavaScript 的下一代标准,涵盖了 ES2015.ES2016.ES2017语法标准.

  • JS快速掌握ES6的class用法

    1.如何构造? 先复习一下es5常用的构建类的方法:首先es5的写法使用原型进行对象的方法的,为什么不在构造函数里添加方法呢?因为实例化对象的时候,会重复的建立好多相同的方法,浪费资源.所以需要把对象的方法挂载到prtotype里. 关于new和this的绑定问题,可以大概简化为: 首先通过new生成一个新的对象 然后让这个对象绑定到构造函数的this中去 然后绑定这个构造对象的原型对象上 最后把这个对象返回给前面定义的对象 那么接下来看例子吧: fuction Animal(name,age)

  • JavaScript ES6解构运算符的理解和运用

    目录 前言 解构符号的作用 使用方法 解构赋值的应用 浅谈应用 提取json数据 可扩展运算符... 交换变量值 总结 前言 最近一直在学JavaScript,看到了ES6中的解构符号,觉得这个给我们的代码简洁性带来了一个飞跃式的提升,而且它已经运用在了企业开发中,假如未来你工作中,别人在用,你却读不懂别人的代码,这造成的影响还是很大的.因此,好好学习一下吧. 你可以不用,但是你不能不懂✔ JavaScript ES6中,有很多特性都是为了简化代码,方便程序员去书写的.解构运算符就是其中很好的特

  • 详解Node.js如何处理ES6模块

    一.两种模块的差异 ES6 模块和 CommonJS 模块有很大的差异. 语法上面,CommonJS 模块使用require()加载和module.exports输出,ES6 模块使用import和export. 用法上面,require()是同步加载,后面的代码必须等待这个命令执行完,才会执行.import命令则是异步加载,或者更准确地说,ES6 模块有一个独立的静态解析阶段,依赖关系的分析是在那个阶段完成的,最底层的模块第一个执行. 二.Node.js 的区分 Node.js 要求 ES6

  • 详解JS ES6变量的解构赋值

    1.什么是解构? ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构.它在语法上比ES5所提供的更加简洁.紧凑.清晰.它不仅能减少你的代码量,还能从根本上改变你的编码方式. 2.数组解构 以前,为变量赋值,我们只能直接指定值,比如 let a = 1; let b = 2; let c = 3; 现在可以用数组解构的方式来进行赋值 let [a, b, c] = [1, 2, 3]; console.log(a, b, c); // 1, 2, 3 这是数组解构最基本类型

  • java设计模式之观察者模式的介绍及使用

    一.定义 观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象(通知者).这个主题对象观察到被观察者发生变化时,会通知所有的观察者对象,使它们能够自己更新自己 这里涉及了几个角色及他们自己功能: 观察者对象:可以更新自己 主题对象:可以添加观察者,移除观察者,通知观察者 被观察者:被主题对象监视,当被观察者发生变化时,主题对象会通知观察者更新自己的状态 二.使用场景 当一个对象改变需要同时改变其他对象的时候,而且不需要知道有多少个对象需要改变 三.举个例子 如果干巴巴的概

  • JavaScript es6中var、let以及const三者区别案例详解

    首先,一个常见的问题是,ECMAScript 和 JavaScript 到底是什么关系?         ECMAScript是一个国际通过的标准化脚本语言.JavaScript由ECMAScript和DOM.BOM三者组成.可以简单理解为:ECMAScript是JavaScript的语言规范,JavaScript是ECMAScript的实现和扩展.         2011 年,ECMAScript 5.1 版发布.之前我们大部分人用的也就是ES5         2015 年 6 月,ECM

  • JavaScript实现简易轮播图最全代码解析(ES6面向对象)

    本文实例为大家分享了JavaScript实现简易轮播图的具体代码,供大家参考,具体内容如下 完整代码: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>ES6轮播图</title> <script></script> <style> * { margin: 0; padding: 0; } .box { wi

  • 详解JS ES6编码规范

    1.块级作用域 1.1.let取代var ES6 提出了两个新的声明变量的命令: let 和const.其中,let可以完全取代var,因为两者语义相同,而且let没有副作用. var命令存在变量提升的特性,而let没有这个命令. 所谓变量提升,即指变量可以先使用,再声明,显然,这种编码规范非常不适合阅读. 1.2.全局常量和线程安全 在let和const之间,优先使用const. let应出现在单线程模块代码内,而const则非常适合多线程. // bad var a = 1, b = 2,

  • JS ES6展开运算符的几个妙用

    1. 添加属性 复制对象的同时,为其添加新的属性. 例子中复制了user对象到userWithPass,并添加了password属性. const user = { id: 110, name: 'Kayson Li'} const userWithPass = { ...user, password: 'Password!' } user //=> { id: 110, name: 'Kayson Li'} userWithPass //=> { id: 110, name: 'Kayson

随机推荐