javaScript购物车案例

1、静态页面

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <style type="text/css">
      * {
        margin: 0;
        padding: 0;
        text-decoration: none;
        list-style: none;
      }
      body {
        background: #ea4335;
      }
      .main {
        width: 800px;
        margin: auto;
        margin-top: 20px;
      }
      .top {
        background: #fff;
        padding: 10px;
      }
      .ipt {
        width: 230px;
        height: 32px;
        line-height: 32px;
        border: 1px solid #ccc;
      }
      .btn {
        height: 34px;
        width: 120px;
        border: none;
      }

      .cart {
        background: #fff;
        margin-top: 20px;
        padding: 10px;
      }
      .cart .tr {
        height: 35px;
      }
      .cart .tr div {
        float: left;
        line-height: 35px;
      }
      .cart .tr {
        padding: 5px 0px;
        border-bottom: 1px solid #ccc;
      }
      .cart .tr {
        clear: both;
      }
      .cart .tr div:nth-child(1) {
        width: 20%;
      }
      .cart .tr div:nth-child(2) {
        width: 20%;
      }
      .cart .tr div:nth-child(3) {
        width: 20%;
      }
      .cart .tr div:nth-child(4) {
        width: 30%;
      }
      .cart .tr div:nth-child(5) {
        width: 10%;
      }
      .cart .tr input {
        width: 50px;
      }

      .footer {
        background: #fff;
        margin-top: 20px;
        padding: 10px;
      }
      #amount {
        color: red;
      }
    </style>
  </head>
  <body>
    <div class="main">
      <div class="top">
        商品名称:<input type="text" name="" value="" id="title" class="ipt" /> 商品价格:<input type="text" name="" value="" id="price" class="ipt" />
        <input type="button" value="加入购物车" class="btn" id="addcart" />
      </div>
      <div class="cart">
        <div class="tr">
          <div><input type="checkbox" name="" value="" id="selectAll" /> 全选按钮</div>
          <div>商品名称</div>
          <div>商品价格</div>
          <div>数量</div>
          <div>操作</div>
        </div>
        <div id="goods">
          <div class="tr" id="1655771835688">
            <div><input type="checkbox" name="ckboxs" value="1655771835688" /></div>
            <div>鼠标</div>
            <div>100元</div>
            <div>
              <a href="javascript:;" name="-">-</a>
              <input type="text" value="1" readonly="" />
              <a href="javascript:;" name="+">+</a>
            </div>
            <div><a href="javascript:;" name="del">删除</a></div>
          </div>
        </div>
      </div>
      <div class="footer">
        总共<span id="count">0</span>件商品,共计 <span id="amount">0</span> 元
        <a href="javascript:;" class="r" id="delall">清空购物车</a>
      </div>
    </div>
  </body>
</html>

2、模拟数据、渲染数据 

class Cart {
  // 1、模拟数据
  goods = [
    { id: 1, title: "电脑", price: 100, num: 1, checked: true },
    { id: 2, title: "鼠标", price: 50, num: 1, checked: false },
    { id: 3, title: "键盘", price: 80, num: 1, checked: true },
  ];
  //获取goods节点
  goodsNode = document.getElementById("goods");

  //渲染数据
  render(h) {
    var str = "";
    for (var i = 0; i < this.goods.length; i++) {//循环拼接结构
      str += ` <div class="tr" id="${this.goods[i].id}">
        <div><input type="checkbox" name="ckboxs" value="1655771835688" ${this.goods[i].checked?'checked':''} /></div>
        <div>${this.goods[i].title}</div>
        <div>${this.goods[i].price}元</div>
        <div>
        <a href="javascript:;" name="-">-</a>
        <input type="text" value="${this.goods[i].num}" readonly="" />
        <a href="javascript:;" name="+">+</a>
        </div>
        <div><a href="javascript:;" name="del">删除</a></div>
    </div>`;
    }
    this.goodsNode.innerHTML = str;
  }
}
var mycart = new Cart();
mycart.render();

3、点击购物车,添加商品

class Cart {
  // 1、模拟数据
  goods = [
    { id: 1, title: "电脑", price: 100, num: 1, checked: true },
    { id: 2, title: "鼠标", price: 50, num: 1, checked: false },
    { id: 3, title: "键盘", price: 80, num: 1, checked: true },
  ];

  //constructor 初始化执行
  constructor() {
    this.render();
    this.addevent();
  }
  //获取goods节点
  goodsNode = document.getElementById("goods");
  //3.1 获取添加购物车按钮节点
  addcartNode = document.getElementById("addcart");
  // 3.4 获取商品名,商品价格输入框节点
  titleNode = document.getElementById("title");
  priceNode = document.getElementById("price");

  //所有监听事件的函数
  addevent() {
    // 3.3 保存当前实例的this
    var _this = this;
    // 3.2 addcart添加购物车按钮的点击事件
    this.addcartNode.addEventListener("click", function () {
      // console.log(this); //注意,此时的this是addcart按钮
      //3.5获取用户输入的商品名以及价格,传递给保存数据函数,注意一个函数只做一件事
      var title = _this.titleNode.value;
      var price = _this.priceNode.value;
      //3.9、如果用户输入为空,则返回
      if (title == "" || price == "") return;
      //   console.log(title,price);
      _this.saveData(title, price);
      //3.8 添加完数据后,将输入框内容变为空
      _this.titleNode.value = "";
      _this.priceNode.value = "";
    });
  }
  //3.6 saveData
  saveData(title, price) {
    var obj = {
      id: Date.now(),
      title: title,
      price: price,
      num: 1,
      checked: true,
    };
    this.goods.unshift(obj);
    // 3.7 数据准备好后,重新渲染函数
    // console.log(this.goods);
    this.render();
  }

  //2、渲染数据
  render(h) {
    ······
  }
}
var mycart = new Cart();
mycart.render();

4、修改复选框状态

class Cart {
  // 1、模拟数据
  goods = [
    { id: 1, title: "电脑", price: 100, num: 1, checked: true },
    { id: 2, title: "鼠标", price: 50, num: 1, checked: false },
    { id: 3, title: "键盘", price: 80, num: 1, checked: true },
  ];

  //constructor 初始化执行
  constructor() {
    this.render();
    this.addevent();
  }
  //获取goods节点
  goodsNode = document.getElementById("goods");
  ·····

  //所有监听事件的函数
  addevent() {
    ·····
    // 4、监听复选框状态,采用事件委托,监听goodsNode
    this.goodsNode.addEventListener("click", function (e) {
      //4.1 e.target.name 获取目标对象身上的name属性,用来标识点击对象的不同,从而有不同的处理逻辑
      if (e.target.name == "ckboxs") {
        // 4.2 获取点击按钮的id,以及状态,传递给修改函数,进行数据的修改
        var id = e.target.parentNode.parentNode.id;
        var checked = e.target.checked;
        // console.log(id, checked);
        _this.editDate(id, "checked", checked);
      }
    });
  }
  //  4.3 、修改数据函数,修改哪个id,哪个属性,哪个值
  editDate(id, key, value) {
    // 4.4遍历数据,筛选出,要修改哪条数据,然后把对应属性以及属性值修改了
    for (let index = 0; index < this.goods.length; index++) {
      if (this.goods[index].id == id) {
        this.goods[index][key] = value;
      }
    }
    // 4.4 修改后,需要重新渲染
    this.render();
    // console.log(this.goods);
  }
  ······

5、修改+ -

  //所有监听事件的函数
  addevent() {
        ·····
      //   5.1 、监听+ -
      if (e.target.name == "+" || e.target.name == "-") {
        // 5.2 拿到修改值的id,以及num的值
        var id = e.target.parentNode.parentNode.id;
        var num;
        for (let index = 0; index < _this.goods.length; index++) {
          if (_this.goods[index].id == id) {
            num = _this.goods[index].num;
          }
        }
        // 5.3判断点击的是+,还是-,进行数字的改变
        if (e.target.name == "+") {
          num++;
        } else {
          num--;
        }
        if (num <= 0) {
          num = 1;
        }
        // 5.4  将准备的ID,num传递该修改数据函数
        _this.editDate(id, "num", num);
      }
    });
  }

6、删除商品

  //所有监听事件的函数
  addevent() {
    ····
      //6、1删除商品
      if ((e.target.name = "del")) {
        //6.2 获取点击删除按钮的id
        var id = e.target.parentNode.parentNode.id;
        //6.3 将准备好的id传递给删除函数
        _this.delData(id);
      }
    });
  }
  //6、删除数据函数  id,删除哪个数据
  delData(id) {
    // 方法一:
    // var newData = [];
    // for (let index = 0; index < this.goods.length; index++) {
    //   if (id != this.goods[index].id) {
    //     newData.push(this.goods[index]);
    //   }
    // }
    // this.goods = newData;
    // this.render();
    // 方法二:
    this.goods = this.goods.filter(function (item) {
      return item.id != id;
    });
    this.render();
  }

7、全选与反选

// 4、监听复选框状态,采用事件委托,监听goodsNode
 this.goodsNode.addEventListener("click", function (e) {
        ·····
    // 7、全选按钮
    this.selectAllNode.addEventListener("click", function (e) {
      //7.2 获取全选按钮的状态,全选按钮的状态跟每个商品的状态一直
      var isAllChecked = e.target.checked;
      //7.3 传递全选状态给处理函数
      _this.selectAll(isAllChecked);
    });
  }
  
  //7.4、全选与反全选
  selectAll(isAllChecked) {
    for (let index = 0; index < this.goods.length; index++) {
      this.goods[index].checked = isAllChecked;
    }
    this.render();
  }

8、选中全部的单选,全选

 //所有监听事件的函数
  addevent() {
    ·····
    // 4、监听复选框状态,采用事件委托,监听goodsNode
    this.goodsNode.addEventListener("click", function (e) {
     ······
        // 8.1、监听复选框状态,如果全部为true,则全选按钮为true
        _this.editSelectAll();
      }
    });
    ·····
    
  // 8.2、处理单选与全选交互
  editSelectAll() {
    // 第一种写法
    // var checked = true; //默认checed状态为true
    // for (let index = 0; index < this.goods.length; index++) {
    //   // 只要商品的单选框没有有没有被选中,则将checked变为false
    //   if (!this.goods[index].checked) {
    //     checked = false;
    //   }
    // }
    // //改变selectAllNode的状态
    // this.selectAllNode.checked = checked;
    // 第二种写法:
    var goodCheck = 0;
    for (let index = 0; index < this.goods.length; index++) {
      if (this.goods[index].checked) {
        goodCheck += 1;
      }
    }
    if (this.goods.length == goodCheck) {
      this.selectAllNode.checked = true;
    } else {
      this.selectAllNode.checked = false;
    }
  }

9、清空购物车

 // 9.1 获取清空购物车按钮
  delallNode = document.getElementById("delall");

  //所有监听事件的函数
  addevent() {
    ·····
    // 9、清空购物车
    this.delallNode.addEventListener("click", function () {
        _this.goods=[]
        _this.render()
    });
}

10、计算商品总数量、总价

 //10.1 获取商品件数,商品总价节点
  countNode = document.getElementById("count");
  amountNode = document.getElementById("amount");
····
  //10、计算底部数据,在初次渲染函数render中,进行渲染,后面,随着用户的操作,也会随着冲洗渲染
  changeFooter() {
    // 计算底部商品件数
    var count = 0;
    var amount = 0;
    for (let index = 0; index < this.goods.length; index++) {
      if (this.goods[index].checked) {
        count += this.goods[index].num;
        amount += this.goods[index].num * this.goods[index].price;
      }
    }
    this.countNode.innerHTML = count;
    this.amountNode.innerHTML = amount;
  }

11、本地存储

  //constructor 初始化执行
  constructor() {
    // 初始化时,从本地拿去数据
    this.goods = localStorage.getItem("goods") ? JSON.parse(localStorage.getItem("goods")) : [];
    this.render();
    this.addevent();
    // 全选按钮,也需要初始化时
    this.editSelectAll()
  }
  ````
  //2、渲染数据
  render() {
    var str = "";
    for (var i = 0; i < this.goods.length; i++) {
      str += ` 
      <div class="tr" id="${this.goods[i].id}">
        <div><input type="checkbox" name="ckboxs" value="1655771835688"  ${this.goods[i].checked ? "checked" : ""} /></div>
        <div>${this.goods[i].title}</div>
        <div>${this.goods[i].price}元</div>
        <div>
            <a href="javascript:;" name="-">-</a>
            <input type="text" value="${this.goods[i].num}" readonly="" />
            <a href="javascript:;" name="+">+</a>
        </div>
        <div><a href="javascript:;" name="del">删除</a></div>
    </div>`;
    }
    this.goodsNode.innerHTML = str;
    // 调用商品总数量,以及总价格
    this.changeFooter();
    // 保存数据到本地
    localStorage.setItem("goods", JSON.stringify(this.goods));
  }

12、es6完整js代码

let _this;
class Cart {
  // 1、模拟数据
  /* 
        { id: 1, title: "电脑", price: 100, num: 1, checked: true },
      { id: 2, title: "鼠标", price: 50, num: 2, checked: false },
      { id: 3, title: "键盘", price: 80, num: 1, checked: true },
    */
  goods = [];
  //获取goods节点
  goodsNode = document.getElementById("goods");
  //3.1 获取添加购物车按钮节点
  addcartNode = document.getElementById("addcart");
  // 3.4 获取商品名,商品价格输入框节点
  titleNode = document.getElementById("title");
  priceNode = document.getElementById("price");
  //7.1 获取全选按钮
  selectAllNode = document.getElementById("selectAll");
  // 9.1 获取清空购物车按钮
  delallNode = document.getElementById("delall");
  //10.1 获取商品件数,商品总价节点
  countNode = document.getElementById("count");
  amountNode = document.getElementById("amount");
  //constructor 初始化执行
  constructor() {
    _this = this;
    // 初始化时,从本地拿去数据
    this.goods = localStorage.getItem("goods") ? JSON.parse(localStorage.getItem("goods")) : [];
    this.render();
    this.addevent();
    // 全选按钮,也需要初始化时
    this.editSelectAll();
  }
  //所有监听事件的函数
  addevent() {
    // 3.3 保存当前实例的this

    // 3.2 addcart添加购物车按钮的点击事件
    this.addcartNode.addEventListener("click", function () {
      // console.log(this); //注意,此时的this是addcart按钮
      //3.5获取用户输入的商品名以及价格,传递给保存数据函数,注意一个函数只做一件事
      var title = _this.titleNode.value;
      var price = _this.priceNode.value;
      //3.9、如果用户输入为空,则返回
      if (title == "" || price == "") return;
      //   console.log(title,price);
      _this.saveData(title, price);
      //   调用是否全选
      _this.editSelectAll();

      //3.8 添加完数据后,将输入框内容变为空
      _this.titleNode.value = "";
      _this.priceNode.value = "";
    });
    // 4、监听复选框状态,采用事件委托,监听goodsNode
    this.goodsNode.addEventListener("click", function (e) {
      //4.1 e.target.name 获取目标对象身上的name属性,用来标识点击对象的不同,从而有不同的处理逻辑
      if (e.target.name == "ckboxs") {
        // 4.2 获取点击按钮的id,以及状态,传递给修改函数,进行数据的修改
        var id = e.target.parentNode.parentNode.id;
        var checked = e.target.checked;
        // console.log(id, checked);
        _this.editDate(id, "checked", checked);
        // 8、监听复选框状态,如果全部为true,则全选按钮为true
        _this.editSelectAll();
      }
      //5.1 、监听+ -
      if (e.target.name == "+" || e.target.name == "-") {
        // 5.2 拿到修改值的id,以及num的值
        var id = e.target.parentNode.parentNode.id;
        var num;
        for (let index = 0; index < _this.goods.length; index++) {
          if (_this.goods[index].id == id) {
            num = _this.goods[index].num;
          }
        }
        // 5.3判断点击的是+,还是-,进行数字的改变
        if (e.target.name == "+") {
          num++;
        } else {
          num--;
        }
        if (num <= 0) {
          num = 1;
        }
        // 5.4  将准备的ID,num传递该修改数据函数
        _this.editDate(id, "num", num);
      }
      //6、1删除商品
      if (e.target.name == "del") {
        //6.2 获取点击删除按钮的id
        var id = e.target.parentNode.parentNode.id;
        //6.3 将准备好的id传递给删除函数
        _this.delData(id);
      }
    });
    // 7、全选按钮
    this.selectAllNode.addEventListener("click", function (e) {
      //7.2 获取全选按钮的状态,全选按钮的状态跟每个商品的状态一直
      var isAllChecked = e.target.checked;
      //7.3 传递全选状态给处理函数
      _this.selectAll(isAllChecked);
    });
    // 9、清空购物车
    this.delallNode.addEventListener("click", function () {
      _this.goods = [];
      _this.render();
    });
  }
  //10、计算底部数据,在初次渲染函数render中,进行渲染,后面,随着用户的操作,也会随着冲洗渲染
  changeFooter() {
    // 计算底部商品件数
    var count = 0;
    var amount = 0;
    for (let index = 0; index < this.goods.length; index++) {
      if (this.goods[index].checked) {
        count += this.goods[index].num;
        amount += this.goods[index].num * this.goods[index].price;
      }
    }
    this.countNode.innerHTML = count;
    this.amountNode.innerHTML = amount;
  }
  // 8、处理单选与全选交互
  editSelectAll() {
    // 第一种写法
    // var checked = true; //默认checed状态为true
    // for (let index = 0; index < this.goods.length; index++) {
    //   // 只要商品的单选框没有有没有被选中,则将checked变为false
    //   if (!this.goods[index].checked) {
    //     checked = false;
    //   }
    // }
    // //改变selectAllNode的状态
    // this.selectAllNode.checked = checked;
    // 第二种写法:
    var goodCheck = 0;
    for (let index = 0; index < this.goods.length; index++) {
      if (this.goods[index].checked) {
        goodCheck += 1;
      }
    }
    if (this.goods.length != goodCheck || this.goods.length == 0) {
      this.selectAllNode.checked = false;
    } else {
      this.selectAllNode.checked = true;
    }
  }
  //7.4、全选与反全选
  selectAll(isAllChecked) {
    for (let index = 0; index < this.goods.length; index++) {
      this.goods[index].checked = isAllChecked;
    }
    this.render();
  }

  //6、删除数据函数  id,删除哪个数据
  delData(id) {
    //     // 方法一:
    //     // var newData = [];
    //     // for (let index = 0; index < this.goods.length; index++) {
    //     //   if (id != this.goods[index].id) {
    //     //     newData.push(this.goods[index]);
    //     //   }
    //     // }
    //     // this.goods = newData;
    //     // this.render();
    //     // 方法二:
    this.goods = this.goods.filter(function (item) {
      return item.id != id;
    });
    _this.editSelectAll();
    this.render();
  }

  //  4.3 、修改数据函数,修改哪个id,哪个属性,哪个值
  editDate(id, key, value) {
    // 4.4遍历数据,筛选出,要修改哪条数据,然后把对应属性以及属性值修改了
    for (let index = 0; index < this.goods.length; index++) {
      if (this.goods[index].id == id) {
        this.goods[index][key] = value;
      }
    }
    // 4.4 修改后,需要重新渲染
    this.render();
    // console.log(this.goods);
  }

  //3.6 saveData 保存数据
  saveData(title, price) {
    var obj = {
      id: Date.now(),
      title: title,
      price: price,
      num: 1,
      checked: true,
    };
    this.goods.unshift(obj);
    // 3.7 数据准备好后,重新渲染函数
    // console.log(this.goods);
    this.render();
  }

  //2、渲染数据
  render() {
    var str = "";
    for (var i = 0; i < this.goods.length; i++) {
      str += ` 
        <div class="tr" id="${this.goods[i].id}">
          <div><input type="checkbox" name="ckboxs" value="1655771835688"  ${this.goods[i].checked ? "checked" : ""} /></div>
          <div>${this.goods[i].title}</div>
          <div>${this.goods[i].price}元</div>
          <div>
              <a href="javascript:;" name="-">-</a>
              <input type="text" value="${this.goods[i].num}" readonly="" />
              <a href="javascript:;" name="+">+</a>
          </div>
          <div><a href="javascript:;" name="del">删除</a></div>
      </div>`;
    }
    this.goodsNode.innerHTML = str;
    // 调用商品总数量,以及总价格
    this.changeFooter();
    // 保存数据到本地
    localStorage.setItem("goods", JSON.stringify(this.goods));
  }
}
var mycart = new Cart();
mycart.render();

13、es5购物车完整代码

let addcart = document.getElementById("addcart"); //加入购物车
let title = document.getElementById("title"); //商品名
let price = document.getElementById("price"); //价格
let goods = document.getElementById("goods"); //商品列表
let selectAll = document.getElementById("selectAll"); //全选
let delallElement = document.getElementById("delall"); //清空购物车

// 点击添加
addcart.addEventListener("click", addcartFun);
function addcartFun() {
  let titleValue = title.value;
  let priceValue = price.value;
  let str = `
    <div class="tr" id="${+new Date()}">
    <div><input type="checkbox" name="ckboxs" value="1655771835688" /></div>
    <div>${titleValue}</div>
    <div>${priceValue}元</div>
    <div>
      <a href="javascript:;" name="-">-</a>
      <input type="text" value="1" readonly="" />
      <a href="javascript:;" name="+">+</a>
    </div>
    <div><a href="javascript:;" name="del">删除</a></div>
  </div>
    `;
  goods.insertAdjacentHTML("beforeend", str);
  //   重新计算总量和价格
  aountNumandPrice();
}

goods.addEventListener("click", clickgoodsFun);
function clickgoodsFun(e) {
  //  点击删除按钮
  if (e.target.name == "del") {
    let tr = e.target.parentNode.parentNode;
    tr.parentNode.removeChild(tr);
    // 重新判断是否要全选
    ckboxChangeSelectAll();
    //   重新计算总量和价格
    aountNumandPrice();
  }
  //点击+
  if (e.target.name == "+") {
    let numInputValue = e.target.previousElementSibling.value;
    numInputValue++;
    e.target.previousElementSibling.value = numInputValue;
    //   重新计算总量和价格
    aountNumandPrice();
  }
  //点击-
  if (e.target.name == "-") {
    let numInputValue = e.target.nextElementSibling.value;
    if (numInputValue >= 2) numInputValue--;
    e.target.nextElementSibling.value = numInputValue;
    //   重新计算总量和价格
    aountNumandPrice();
  }
  //点击单选框
  if (e.target.name == "ckboxs") {
    ckboxChangeSelectAll();
    //   重新计算总量和价格
    aountNumandPrice();
  }
  //  点击单选是否要全选
  function ckboxChangeSelectAll() {
    selectAll.checked = true;
    let ckboxsAll = document.getElementsByName("ckboxs");
    for (let i = 0; i < ckboxsAll.length; i++) {
      if (!ckboxsAll[i].checked) {
        selectAll.checked = false;
      }
    }
  }
}
//  全选按钮
selectAll.addEventListener("click", selectAllFun);
function selectAllFun() {
  let isChecked = selectAll.checked;
  let ckboxsAll = document.getElementsByName("ckboxs");
  for (let i = 0; i < ckboxsAll.length; i++) {
    ckboxsAll[i].checked = isChecked;
  }
  //   重新计算总量和价格
  aountNumandPrice();
}
// 统计数据
function aountNumandPrice() {
  let countElement = document.getElementById("count");
  let amountElement = document.getElementById("amount");
  let count = 0;
  let amount = 0;
  for (let i = 0; i < goods.children.length; i++) {
    // 是否被选中
    let isChecked = goods.children[i].children[0].children[0].checked;
    if (isChecked) {
      let num = +goods.children[i].children[3].children[1].value;
      let price = parseInt(goods.children[i].children[2].innerHTML);
      count += num;
      amount += num * price;
    }
  }
  countElement.innerHTML = count;
  amountElement.innerHTML = amount;
}
aountNumandPrice();
// 清空所有商品
delallElement.addEventListener("click", delallFun);
function delallFun() {
  goods.innerHTML = "";
  aountNumandPrice();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值