博客列表 >JavaScript 购物车案例

JavaScript 购物车案例

尹辉
尹辉原创
2023年04月08日 10:52:31274浏览

JavaScript 购物车案例

以课堂案例为基础,更新以下内容

  • 商品列表 DOM 结构由脚本动态生成

  • 修复课堂案例中点击复选框后再改变数量时数据不准确的问题

脚本动态生成 DOM 结构

  1. // (一) 从购物车模块中获取数据
  2. import carts from './carts.js'
  3. // (二) 根据 carts.data 生成对应的商品列表(<tr>),同时将商品数据渲染到页面
  4. const cartsBody = document.querySelector('.carts-body')
  5. carts.data.forEach((item) => {
  6. // 创建临时 elemFlag
  7. const elemFlag = document.createDocumentFragment()
  8. // 每条数据创建一个<tr>元素
  9. const trElem = document.createElement('tr')
  10. trElem.classList.add('item')
  11. // 为<tr>创建对应的单元格<td>
  12. // 第一个<td>: checkbox
  13. // <td><input type="checkbox" name="" class="check" checked /></td>
  14. const tdElem = document.createElement('td')
  15. const checkElem = document.createElement('input')
  16. checkElem.type = 'checkbox'
  17. checkElem.name = ''
  18. checkElem.classList.add('check')
  19. checkElem.checked = true
  20. tdElem.append(checkElem)
  21. trElem.append(tdElem)
  22. // 将当前data数据放置到对应的单元格<td>
  23. for (let key in item) {
  24. const tdElem = document.createElement('td')
  25. if (key === 'num') {
  26. // <td><input type="number" name="" class="num" value="1" min="1" /></td>
  27. const numInput = document.createElement('input')
  28. numInput.type = 'number'
  29. numInput.name = ''
  30. numInput.classList.add(key)
  31. numInput.value = item[key]
  32. numInput.min = '1'
  33. tdElem.append(numInput)
  34. trElem.append(tdElem)
  35. } else {
  36. tdElem.classList.add(key)
  37. tdElem.append(item[key])
  38. trElem.append(tdElem)
  39. }
  40. }
  41. elemFlag.append(trElem)
  42. cartsBody.append(elemFlag)
  43. })
  44. // (三) 将总数量、总金额渲染到页面中
  45. // 1. 总数量 carts.total
  46. const total = document.querySelector('.carts-foot .total')
  47. total.textContent = carts.total
  48. // 2. 总金额 carts.totalMoney
  49. const totalMoney = document.querySelector('.carts-foot .total-money')
  50. totalMoney.textContent = carts.totalMoney

修复课堂案例中点击复选框后再改变数量时数据不准确的问题

思路:

  • 将获取的数量(NodeList)、金额(NodeList)转换为数组,得到数量数组(numsArr)和 金额数组(moniesArr)
  • 在复选框事件中动态更新数量数组(numsArr)和 金额数组(moniesArr)
    • 取消选择:从数组中删除对应的商品,但数组中对应的元素位置保留,重新选择时可用赋值添加
      • delete numsArr[index]
      • delete moniesArr[index]
    • 选择:
      • numsArr[index] = curNum
      • moniesArr[index] = curMoney
  • 所有事件中,都通过动态更新的数量数组(numsArr)和 金额数组(moniesArr)来计算总数量和总金额( calc.js 模块中定义的计算函数)

代码

  • html文件中的脚本

    1. import * as calc from './calc.js'
    2. // (四) 获取购物车商品的复选框、数量、单价、金额构成的 NodeList
    3. // 单价(NodeList),用于数量改变时计算金额
    4. const prices = document.querySelectorAll('.carts-body .price')
    5. // 数量(NodeList => Array)
    6. const nums = document.querySelectorAll('.carts-body .num')
    7. let numsArr = [...nums]
    8. // 金额数组(NodeList => Array)
    9. const monies = document.querySelectorAll('.carts-body .money')
    10. let moniesArr = [...monies]
    11. // check数组(NodeList),用于判断是否选中
    12. const checks = document.querySelectorAll('.carts-body .check')
    13. // (五) 为数量控件添加 change 事件
    14. nums.forEach(function (num, index) {
    15. num.onchange = function () {
    16. // 1. 计算当前商品金额 = 数量 * 单价
    17. // 未选择时也可用更改数量及对应的金额,只是不计入汇总
    18. monies[index].textContent = (num.value * prices[index].textContent).toString()
    19. // 2. 计算总数量并渲染到页面
    20. total.textContent = calc.calcTotalNum(numsArr)
    21. // 3. 计算总金额并渲染到页面
    22. totalMoney.textContent = calc.calcTotalMoney(moniesArr)
    23. }
    24. })
    25. // (六) 复选框
    26. // 全选按钮
    27. const checkAll = document.querySelector('.check-all')
    28. // 为全选添加change
    29. checkAll.onchange = function () {
    30. // 遍历所有商品的状态,并将当前全选按钮的状态赋值给它
    31. checks.forEach(check => check.checked = checkAll.checked)
    32. // 根据所有商品的全选/全不选状态,更新 数量数组 numsArr 和 金额数组 moniesArr
    33. // 全不选
    34. if (false === this.checked) {
    35. // 删除数量数组中的所有数据,重新计算总数量并渲染到页面
    36. for (let i = 0; i < numsArr.length; i++) {
    37. delete numsArr[i]
    38. }
    39. total.textContent = calc.calcTotalNum(numsArr)
    40. // 删除金额数组中的所有数据,重新计算总数量并渲染到页面
    41. for (let i = 0; i < moniesArr.length; i++) {
    42. delete moniesArr[i]
    43. }
    44. totalMoney.textContent = calc.calcTotalMoney(moniesArr)
    45. } else {
    46. // 全选
    47. // 从 NodeList 中重新获取数量数组,重新计算总数量并渲染到页面
    48. numsArr = [...nums]
    49. total.textContent = calc.calcTotalNum(numsArr)
    50. // 从 NodeList 中重新获取金额数组,重新计算总金额并渲染到页面
    51. moniesArr = [...monies]
    52. totalMoney.textContent = calc.calcTotalMoney(moniesArr)
    53. }
    54. }
    55. // 遍历每个商品的复选框,并添加change,动态的计算相关数据
    56. checks.forEach(function (check, index) {
    57. check.onchange = function () {
    58. // 根据所有商品的复选框的状态,来动态的设置全选
    59. checkAll.checked = [...checks].every(check => check.checked)
    60. // 如果商品未选中,从数量数组和金额数组中减去相应的数据,并重新计算总数量和总金额
    61. // 如果商品选中,从数量数组和金额数组中添加相应的数据,并重新计算总数量和总金额
    62. if (false === check.checked) {
    63. // 将当前数量对应的<input>元素,从数量数组中删除,重新计算总数量并渲染到页面
    64. delete numsArr[index]
    65. total.textContent = calc.calcTotalNum(numsArr)
    66. // 将当前金额对应的<td>元素,从金额数组中删除,重新计算总金额并渲染到页面
    67. delete moniesArr[index]
    68. totalMoney.textContent = calc.calcTotalMoney(moniesArr)
    69. } else {
    70. // 获取当前商品对应的行元素<tr>
    71. const curTr = this.parentElement.parentElement
    72. // 获取当前商品金额对应的单元格元素<td>
    73. const curMoney = curTr.lastElementChild
    74. // 获取当前商品数量对应的<input>元素
    75. const curNum = curMoney.previousElementSibling.firstElementChild
    76. // 将当前数量对应的<input>元素,添加到数量数组,重新计算总数量并渲染到页面
    77. numsArr[index] = curNum
    78. total.textContent = calc.calcTotalNum(numsArr)
    79. // 将当前金额对应的<td>元素,添加到金额数组,重新计算总金额并渲染到页面
    80. moniesArr[index] = curMoney
    81. totalMoney.textContent = calc.calcTotalMoney(moniesArr)
    82. }
    83. }
  • calc.js 模块

  1. export function calcTotalNum(arr)
  2. {
  3. let tempTotal = 0
  4. arr.forEach((item) => tempTotal += parseInt(item.value))
  5. return tempTotal
  6. }
  7. export function calcTotalMoney(arr) {
  8. let tempTotalMoney = 0
  9. arr.forEach((item) => tempTotalMoney += parseInt(item.textContent))
  10. return tempTotalMoney
  11. }

页面效果

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