Blogger Information
Blog 29
fans 0
comment 0
visits 11149
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
JavaScript 购物车案例
尹辉
Original
276 people have browsed it

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. }

页面效果

Correcting teacher:PHPzPHPz

Correction status:qualified

Teacher's comments:
Statement of this Website
The copyright of this blog article belongs to the blogger. Please specify the address when reprinting! If there is any infringement or violation of the law, please contact admin@php.cn Report processing!
All comments Speak rationally on civilized internet, please comply with News Comment Service Agreement
0 comments
Author's latest blog post