博客列表 >原生JS实现购物车自动结算功能

原生JS实现购物车自动结算功能

longlong
longlong原创
2020年08月22日 13:48:362418浏览

1. JS实现购物车自动结算

1.1 html部分:

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  6. <title>购物车全选以及结算</title>
  7. <link rel="stylesheet" href="demo2.css" />
  8. </head>
  9. <body>
  10. <table class="shopping">
  11. <caption>
  12. <h3>购物车</h3>
  13. </caption>
  14. <thead>
  15. <tr>
  16. <th>
  17. <input type="checkbox" name="checkAll" id="checkAll" checked />
  18. <label for="">全选</label>
  19. </th>
  20. <th>ID</th>
  21. <th>品名</th>
  22. <th>单位</th>
  23. <th>单价</th>
  24. <th>数量</th>
  25. <th>金额</th>
  26. </tr>
  27. </thead>
  28. <tbody>
  29. <tr>
  30. <td><input type="checkbox" name="checkOnly" checked /></td>
  31. <td>1010</td>
  32. <td>商品一</td>
  33. <td></td>
  34. <td>300</td>
  35. <td><input type="number" name="shopNum" value="1" /></td>
  36. <td></td>
  37. </tr>
  38. <tr>
  39. <td><input type="checkbox" name="checkOnly" checked /></td>
  40. <td>1010</td>
  41. <td>商品二</td>
  42. <td></td>
  43. <td>500</td>
  44. <td><input type="number" name="shopNum" value="1" /></td>
  45. <td></td>
  46. </tr>
  47. <tr>
  48. <td><input type="checkbox" name="checkOnly" checked /></td>
  49. <td>1010</td>
  50. <td>商品三</td>
  51. <td></td>
  52. <td>800</td>
  53. <td><input type="number" name="shopNum" value="1" /></td>
  54. <td></td>
  55. </tr>
  56. <tr>
  57. <td><input type="checkbox" name="checkOnly" checked /></td>
  58. <td>1010</td>
  59. <td>商品四</td>
  60. <td></td>
  61. <td>1000</td>
  62. <td><input type="number" name="shopNum" value="1" /></td>
  63. <td></td>
  64. </tr>
  65. <tr>
  66. <td><input type="checkbox" name="checkOnly" checked /></td>
  67. <td>1010</td>
  68. <td>商品五</td>
  69. <td></td>
  70. <td>2000</td>
  71. <td><input type="number" name="shopNum" value="1" /></td>
  72. <td></td>
  73. </tr>
  74. </tbody>
  75. <tfoot>
  76. <tr>
  77. <td colspan="5">总计</td>
  78. <td></td>
  79. <td></td>
  80. </tr>
  81. </tfoot>
  82. </table>
  83. <div class="account">
  84. <button>结算</button>
  85. </div>
  86. <script src="demo.js"></script>
  87. </body>
  88. </html>

1.2 CSS部分:

  1. * {
  2. margin: 0;
  3. padding: 0;
  4. box-sizing: border-box;
  5. }
  6. .shopping {
  7. margin: auto;
  8. width: 90%;
  9. border: 1px solid;
  10. text-align: center;
  11. border-collapse: collapse;
  12. }
  13. .shopping th,
  14. td {
  15. border: 1px solid;
  16. padding: 8px;
  17. }
  18. .shopping caption h3 {
  19. padding: 10px;
  20. }
  21. .shopping thead tr {
  22. background: lightcoral;
  23. }
  24. .shopping tbody tr:nth-of-type(even) {
  25. background: lightcyan;
  26. }
  27. .account {
  28. width: 90%;
  29. margin: auto;
  30. text-align: right;
  31. padding-top: 10px;
  32. }
  33. .account button {
  34. width: 100px;
  35. padding: 5px;
  36. background: green;
  37. color: white;
  38. outline: none;
  39. border: none;
  40. }
  41. .account button:hover {
  42. cursor: pointer;
  43. background: rgb(5, 168, 5);
  44. }

1.3 JS部分:

  1. // 1. 实现全选和全不选效果
  2. // 1.1 获取到全选项和下面的单选项
  3. var checkAll = document.querySelector("#checkAll");
  4. var checkOnlys = document.getElementsByName("checkOnly");
  5. checkAll.addEventListener("change", checkAllBtn, false);
  6. function checkAllBtn() {
  7. checkOnlys.forEach(function (item) {
  8. // 1.2 如果全选项的checked为true,下面所有单选项都为true,反之为false
  9. item.checked = checkAll.checked;
  10. var findNum = item.parentNode.parentNode.children.item(5).childNodes[0];
  11. // 1.3 如果全选为false,数量单元被禁用,并且值全部为0
  12. if (checkAll.checked) {
  13. findNum.disabled = false;
  14. } else {
  15. findNum.disabled = true;
  16. findNum.value = 0;
  17. document.querySelector("tfoot tr td:nth-of-type(2)").innerHTML = 0;
  18. findNum.parentNode.nextElementSibling.innerHTML = 0;
  19. document.querySelector("tfoot tr td:last-of-type").innerHTML = 0;
  20. }
  21. });
  22. }
  23. // 2. 设置下面单个选项控制全选效果
  24. checkOnlys.forEach(function (item) {
  25. item.addEventListener("change", controlCheckAll, false);
  26. });
  27. function controlCheckAll(ev) {
  28. // 2.1 获取到当前所有checked值为true单选项,用它的长度和单选项总的长度对比,如果长度一样,表示所有单选项被选中,那么设置全选想为true
  29. // 反之,若长度不一样,说明至少有一个单选项没有checked,那么设置全选项为false
  30. var checkedNum = document.querySelectorAll(
  31. "input[type=checkbox]:not(#checkAll):checked"
  32. );
  33. checkAll.checked = checkOnlys.length === checkedNum.length;
  34. // 2.2 设置取消单选项时,不要计算单元金额、总数量以及总金额
  35. // 通过当前取消的单选项(ev.target),找到此选项对应的数量单元格,并将此单元格的value改为0
  36. var findNum = ev.target.parentNode.parentNode.children.item(5).childNodes[0];
  37. if (!ev.target.checked) {
  38. findNum.value = 0;
  39. findNum.disabled = true;
  40. // 将取消的单元项的单元金额也设为0
  41. findNum.parentNode.nextElementSibling.innerHTML = 0;
  42. // 获取除取消的单元项以外的单元项,并计算它们的总数量以及总金额
  43. var newNumSum = 0;
  44. var newMoneySum = 0;
  45. shoppingNums.forEach(function (item, index) {
  46. newNumSum += parseInt(item.value);
  47. });
  48. totalNum.innerHTML = newNumSum;
  49. unitMoneys.forEach(function (item, index) {
  50. newMoneySum += parseInt(item.innerHTML);
  51. });
  52. totalMoney.innerHTML = newMoneySum;
  53. } else {
  54. findNum.disabled = false;
  55. }
  56. }
  57. // 3. 监听数量的变化,从而动态改变单元金额、总金额和总数量的值
  58. // 3.1 获取到所有的数量单元,金额单元,单价单元,总数量,总金额
  59. var shoppingNums = document.getElementsByName("shopNum"); // 数量单元
  60. var unitMoneys = document.querySelectorAll("tbody tr td:last-of-type"); // 金额单元
  61. var units = document.querySelectorAll("tbody tr td:nth-of-type(5)"); //单价单元
  62. var totalNum = document.querySelector("tfoot tr td:nth-of-type(2)"); //总数量
  63. var totalMoney = document.querySelector("tfoot tr td:last-of-type"); //总金额
  64. // 3.2 设置默认值
  65. var numSum = 0;
  66. var moneySum = 0;
  67. unitMoneys.forEach(function (item, index) {
  68. // 获取每个单元的金额
  69. item.innerHTML = units[index].innerHTML * shoppingNums[index].value;
  70. // 获取总的商品数量
  71. numSum += parseInt(shoppingNums[index].value);
  72. // 获取总的商品金额
  73. moneySum += parseInt(unitMoneys[index].innerHTML);
  74. });
  75. totalNum.innerHTML = numSum;
  76. totalMoney.innerHTML = moneySum;
  77. // 3.3 监听数量在变化时,其他单元也动态变化
  78. shoppingNums.forEach(function (item) {
  79. item.addEventListener("input", changeAll, false);
  80. });
  81. function changeAll(ev) {
  82. // 判断:当前变化的数量单元格必须是在被选中的状态下才能变化
  83. if (ev.target.parentNode.parentNode.children.item(0).childNodes[0].checked) {
  84. // 获取到数量变化时单元金额的变化
  85. ev.target.parentNode.nextElementSibling.innerHTML =
  86. ev.target.value * ev.target.parentNode.previousElementSibling.innerHTML;
  87. var nowNumSum = 0;
  88. var nowMoneySum = 0;
  89. // 获取到数量变化时商品总数量的变化
  90. shoppingNums.forEach(function (item, index) {
  91. nowNumSum += parseInt(item.value);
  92. });
  93. totalNum.innerHTML = nowNumSum;
  94. // 获取到数量变化时商品总金额的变化
  95. unitMoneys.forEach(function (item, index) {
  96. nowMoneySum += parseInt(item.innerHTML);
  97. });
  98. totalMoney.innerHTML = nowMoneySum;
  99. }
  100. }

1.4 效果如下:

  • 全选和全不选效果以及取消任一单元项就取消全选:

  • 全选状态下的自动结算:

  • 取消单元项时,其他项也自动结算:

  • 整体效果:

2. 总结

把这次作业当成了一次对自己的考核,没有看视频回放,也没有看老师的代码,全部自己写的,花了几个小时写完以后对照老师的代码,感觉不足之处还是在于对函数的利用,没有做得很好,充分利用好函数才能实现对代码的复用,可能自己的思想层面还没有达到那个程度,现在还停留在对一个方案的逻辑上面,必须再上一层,达到使用函数来构建逻辑,然后再组织代码。

声明:本文内容转载自脚本之家,由网友自发贡献,版权归原作者所有,如您发现涉嫌抄袭侵权,请联系admin@php.cn 核实处理。
全部评论
文明上网理性发言,请遵守新闻评论服务协议