首页>案例集>JavaScript案例集

商城购物车ES6原生js实现零漏洞

以前写购物车,总是或多或少会留下几个小bug被学生捉虫,这次把以前jQuery写的一个商城项目的购物车单独拎出来,用原生js(ES6)再写一次,希望是零漏洞了。

5.jpg

点击图片看效果。

功能:很多很多小细节,就不罗列了,直接上代码。

/* 
  1、点击加减按钮,临界值判断,数量变化,复选框勾上,全选判断,商品价格变化,总商品数量,总价格,结算按钮变化
  2、输入数量,临界值判断,数据合法性判断、复选框勾上,商品价格变化,全选判断,总商品数量,总价格,结算按钮变化
  3、点击复选框,商品总价,总数量,结算按钮变化,影响全选
  4、点击全选,单个复选框,商品总价,总数量,结算按钮变化
  5、点击删除按钮,全选框,全选框的可用性,商品总价,总数量,结算按钮变化
  6、删除选中的商品,全选框,全选框的可用性,商品总价,总数量,结算按钮变化
*/
{
  const max = 5;
  const min = 1;
  // 找对象
  const oTrs = $All('tbody tr');
  const oTotalPrice = $('.fy-cart-totalPrice');
  const oTotalNum = $('.fy-cart-checked-totalNum');
  const oBtnSubmit = $('.fy-cart-btnSubmit');
  const oCheckAlls = $All('.fy-cart-checkAll');
  const oBtnDelAll = $('#fy-cat-delAll');

  oTrs.forEach(function (item) {
    cart(item);
  })

  function cart(oTr) {
    const oBtnAdd = oTr.querySelector('.fy-pro-num-add');
    const oBtnJian = oTr.querySelector('.fy-pro-num-minus');
    const oNum = oTr.querySelector('.fy-pro-num-total');
    const oSinglePrice = oTr.querySelector('.fy-cart-nowSinglePrice');
    const oPrice = oTr.querySelector('.fy-cart-nowTotalPrice');
    const oSingleCheck = oTr.querySelector('.singleCheck');
    const oBtnDel = oTr.querySelector('.fy-del-book');

    // 点击加号
    // 临界值判断,数量变化,复选框勾上,商品价格变化 , 总商品数量,总价格,结算按钮变化
    oBtnAdd.addEventListener('click', function () {
      let num = oNum.value;
      // 数量变化
      num++;
      // 临界值判断
      if (num >= max) {
        this.disabled = true;
      }
      if (oBtnJian.disabled) {
        oBtnJian.disabled = false;
      }
      oNum.value = num;
      // 复选框勾上
      oSingleCheck.checked = true;
      // 商品价格变化
      oPrice.innerHTML = '¥' + (oSinglePrice.innerHTML.slice(1) * num).toFixed(2);
      // 总价格总商品数量
      getTotalNumAndPrice();
      // 结算按钮变化
      isBtnSubmitEnabled();
      // 判断全选
      isCheckAll();
    })

    oBtnJian.addEventListener('click', function () {
      let num = oNum.value;
      // 数量变化
      num--;
      // 临界值判断
      if (num <= min) {
        this.disabled = true;
      }
      if (oBtnAdd.disabled) {
        oBtnAdd.disabled = false;
      }
      oNum.value = num;
      // 复选框勾上
      oSingleCheck.checked = true;
      // 商品价格变化
      oPrice.innerHTML = '¥' + (oSinglePrice.innerHTML.slice(1) * num).toFixed(2);
      // 总价格总商品数量
      getTotalNumAndPrice();
      // 结算按钮变化
      isBtnSubmitEnabled();
      // 判断全选
      isCheckAll();
    })

    //  2、输入数量,临界值判断,复选框勾上,商品价格变化,总商品数量,总价格,结算按钮变化
    oNum.addEventListener('keydown', function (e) {
      let key = e.key;
      console.log(key);
      // 键盘只能输入数字1-9或者取消
      if (!(key >= 1 && key <= 9 || key === 'Backspace')) {
        e.preventDefault();
      }
    })
    // 数量输入框临界值判断
    oNum.addEventListener('input', function (e) {
      let val = this.value;
      console.log(val);
      if (val <= 1) {
        val = 1;
        oBtnJian.disabled = true;
        if (oBtnAdd.disabled) {
          oBtnAdd.disabled = false;
        }
      } else if (val >= max) {
        val = max;
        oBtnAdd.disabled = true;
        if (oBtnJian.disabled) {
          oBtnJian.disabled = false;
        }
      } else {
        oBtnAdd.disabled = false;
        oBtnJian.disabled = false;
      }
      this.value = val;
      // 复选框勾上
      oSingleCheck.checked = true;
      // 商品价格变化
      oPrice.innerHTML = '¥' + (oSinglePrice.innerHTML.slice(1) * val).toFixed(2);
      // 总价格总商品数量
      getTotalNumAndPrice();
      // 结算按钮变化
      isBtnSubmitEnabled();
      // 判断全选
      isCheckAll();
    })

    //  3、点击复选框,商品总价,总数量,结算按钮变化,影响全选
    oSingleCheck.addEventListener('change', function () {
      // 总价格总商品数量
      getTotalNumAndPrice();
      // 结算按钮变化
      isBtnSubmitEnabled();
      // 判断全选
      isCheckAll();

    })

    //  5、点击删除按钮,全选框,商品总价,总数量,结算按钮变化
    oBtnDel.addEventListener('click', function () {
      let parent = this.closest('tr');
      parent.remove();
      // 判断全选
      isCheckAll();
      // 全选框可用性判断
      let oSingleChecks = $All('.singleCheck');
      if (oSingleChecks.length == 0) {
        oCheckAlls.forEach(function (item) {
          item.disabled = true;
          item.checked = false;
        })
      }
      // 总价格总商品数量
      getTotalNumAndPrice();
      // 结算按钮变化
      isBtnSubmitEnabled();
    })
  }

  // 4、点击全选,单个复选框,商品总价,总数量,结算按钮变化
  oCheckAlls.forEach(function (item) {
    item.addEventListener('change', function () {
      console.log(this);
      // 把全选的状态给两个全选框
      // 回调函数内部的this默认指向window对象,可以通过传参,把 this绑定在某个具体的对象上。
      oCheckAlls.forEach(function (item) {
        item.checked = this.checked;
      }, this);
      // 把全选的状态给每一个单个的复选康
      let oSingleChecks = $All('.singleCheck');
      oSingleChecks.forEach(function (item) {
        item.checked = this.checked;
        console.log(this);
      }, this)

      // 总价格总商品数量
      getTotalNumAndPrice();
      // 结算按钮变化
      isBtnSubmitEnabled();
    })
  })

  // 6、删除选中的商品,全选框,商品总价,总数量,结算按钮变化
  oBtnDelAll.addEventListener('click', function (e) {
    let oCheckedInputs = document.querySelectorAll('.singleCheck:checked');
    if (!oCheckedInputs.length) {
      alert('需要先选择一个商品');
      return;
    }
    let result = confirm('你确定要删除吗?');
    // console.log(result);
    if (result) {
      oCheckedInputs.forEach(function (item) {
        item.closest('tr').remove();
      })
    } else {
      e.preventDefault();
    }
    // 全选框可用性判断
    let oSingleChecks = $All('.singleCheck');
    if (oSingleChecks.length == 0) {
      oCheckAlls.forEach(function (item) {
        item.disabled = true;
        item.checked = false;
      })
    }

    // 总价格总商品数量
    getTotalNumAndPrice();
    // 结算按钮变化
    isBtnSubmitEnabled();
  })


  // 计算总的数量和价格
  function getTotalNumAndPrice() {
    // 找到所有被选中的复选框,把里面所有的总价累加求和。
    let oCheckedInputs = document.querySelectorAll('.singleCheck:checked');
    // console.log(oCheckedInputs)
    // 保存每个被选中的复选框对应的商品的总价格。
    let priceArr = [];
    let numArr = [];
    oCheckedInputs.forEach(function (item) {
      let parent = item.closest('tr');
      // console.log(parent);
      let price = +(parent.querySelector('.fy-cart-nowTotalPrice').innerHTML).slice(1);
      let num = +(parent.querySelector('.fy-pro-num-total').value);
      priceArr.push(price);
      numArr.push(num);
    })
    // 把数组里面每个商品的总价进行累加求和,就是所有被选中的商品的总价。
    let totalPrice = priceArr.reduce(function (sum, i) {
      return sum + i;
    }, 0)
    let totalNum = numArr.reduce(function (sum, i) {
      return sum + i;
    }, 0)
    oTotalPrice.innerHTML = totalPrice.toFixed(2);
    oTotalNum.innerHTML = totalNum;
  }

  // 判断提交按钮是否可用
  function isBtnSubmitEnabled() {
    let oCheckedInputs = document.querySelectorAll('.singleCheck:checked');
    let result = [...oCheckedInputs].some(function (item) {
      return item.checked;
    })
    oBtnSubmit.disabled = result ? false : true;
  }

  //判断是否要全选
  function isCheckAll() {
    let oCheckedInputs = document.querySelectorAll('.singleCheck:checked');
    let oSingleChecks = $All('.singleCheck');
    if (oCheckedInputs.length === oSingleChecks.length) {
      oCheckAlls.forEach(function (item) {
        item.checked = true;
      })
    } else {
      oCheckAlls.forEach(function (item) {
        item.checked = false;
      })
    }
  }

  function $(selector) {
    return document.querySelector(selector);
  }
  function $All(selector) {
    return document.querySelectorAll(selector);
  }
}


点赞


2
保存到:

相关文章

发表评论:

◎请发表你卖萌撒娇或一针见血的评论,严禁小广告。

Top