• Vue实现购物车页面


    包括全选反选、数据的统计和本地持久化的处理。

    html

    1. DOCTYPE html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="UTF-8" />
    5. <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    6. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    7. <link rel="stylesheet" href="./css/inputnumber.css" />
    8. <link rel="stylesheet" href="./css/index.css" />
    9. <title>购物车title>
    10. head>
    11. <body>
    12. <div class="app-container" id="app">
    13. <div class="banner-box"><img src="img/fruit.jpg" alt="" />div>
    14. <div class="breadcrumb">
    15. <span>🏠span>
    16. /
    17. <span>购物车span>
    18. div>
    19. <div class="main" v-if="fruitList.length>0">
    20. <div class="table">
    21. <div class="thead">
    22. <div class="tr">
    23. <div class="th">选中div>
    24. <div class="th th-pic">图片div>
    25. <div class="th">单价div>
    26. <div class="th num-th">个数div>
    27. <div class="th">小计div>
    28. <div class="th">操作div>
    29. div>
    30. div>
    31. <div class="tbody" v-for="(item,index) in fruitList" :key="item.id">
    32. <div class="tr" :class="{active:item.isChecked}">
    33. <div class="td"><input type="checkbox" v-model="item.isChecked" />div>
    34. <div class="td"><img :src="item.icon" alt="" />div>
    35. <div class="td">{{item.price}}div>
    36. <div class="td">
    37. <div class="my-input-number">
    38. <button class="decrease" @click="item.num-=1" :disabled="item.num<=0"> - button>
    39. <span class="my-input__inner">{{item.num}}span>
    40. <button class="increase" @click="add(item.id)"> + button>
    41. div>
    42. div>
    43. <div class="td">{{item.num*item.price}}div>
    44. <div class="td"><button @click="del(item.id)">删除button>div>
    45. div>
    46. div>
    47. div>
    48. <div class="bottom">
    49. <label class="check-all">
    50. <input type="checkbox" v-model="isAll"/>
    51. 全选
    52. label>
    53. <div class="right-box">
    54. <span class="price-box">总价  :  ¥ <span class="price">{{allMoney}}span>span>
    55. <button class="pay">结算( {{allNum}} )button>
    56. div>
    57. div>
    58. div>
    59. <div class="empty" v-else>🛒空空如也div>
    60. div>
    61. <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js">script>
    62. <script>
    63. const defaultArr = [
    64. {
    65. id: 1,
    66. icon: "img/火龙果.png",
    67. isChecked: true,
    68. num: 2,
    69. price: 6,
    70. },
    71. {
    72. id: 2,
    73. icon: 'img/荔枝.png',
    74. isChecked: false,
    75. num: 7,
    76. price: 20,
    77. },
    78. {
    79. id: 3,
    80. icon: 'img/榴莲.png',
    81. isChecked: false,
    82. num: 3,
    83. price: 40,
    84. },
    85. {
    86. id: 4,
    87. icon: 'img/鸭梨.png',
    88. isChecked: true,
    89. num: 10,
    90. price: 3,
    91. },
    92. {
    93. id: 5,
    94. icon: 'img/樱桃.png',
    95. isChecked: false,
    96. num: 20,
    97. price: 34,
    98. },
    99. ]
    100. const app = new Vue({
    101. el: '#app',
    102. data: {
    103. // 水果列表
    104. fruitList:JSON.parse(localStorage.getItem('list'))||defaultArr
    105. },
    106. methods: {
    107. del (id){
    108. this.fruitList = this.fruitList.filter(item =>item.id!=id)
    109. },
    110. add(id){
    111. const fruit = this.fruitList.find(item => item.id == id)
    112. fruit.num += 1
    113. }
    114. },
    115. computed:{
    116. isAll:{
    117. get(){
    118. return this.fruitList.every(item => item.isChecked)
    119. },
    120. set(value){
    121. this.fruitList.forEach(item => {
    122. item.isChecked = value
    123. });
    124. }
    125. },
    126. allMoney(){
    127. return this.fruitList.reduce((sum,item) => {
    128. if(item.isChecked){
    129. return sum+item.num*item.price
    130. }
    131. else{
    132. return sum
    133. }
    134. },0)
    135. },
    136. allNum(){
    137. return this.fruitList.reduce((sum,item) => {
    138. if(item.isChecked){
    139. return sum+item.num
    140. }
    141. else{
    142. return sum
    143. }
    144. },0)
    145. }
    146. },
    147. watch:{
    148. fruitList:{
    149. deep:true,
    150. handler(newValue){
    151. localStorage.setItem('list',JSON.stringify(newValue))
    152. }
    153. }
    154. }
    155. })
    156. script>
    157. body>
    158. html>

    css

            index

    1. .app-container {
    2. padding-bottom: 300px;
    3. width: 800px;
    4. margin: 0 auto;
    5. }
    6. @media screen and (max-width: 800px) {
    7. .app-container {
    8. width: 600px;
    9. }
    10. }
    11. .app-container .banner-box {
    12. border-radius: 20px;
    13. overflow: hidden;
    14. margin-bottom: 10px;
    15. }
    16. .app-container .banner-box img {
    17. width: 100%;
    18. }
    19. .app-container .nav-box {
    20. background: #ddedec;
    21. height: 60px;
    22. border-radius: 10px;
    23. padding-left: 20px;
    24. display: flex;
    25. align-items: center;
    26. }
    27. .app-container .nav-box .my-nav {
    28. display: inline-block;
    29. background: #5fca71;
    30. border-radius: 5px;
    31. width: 90px;
    32. height: 35px;
    33. color: white;
    34. text-align: center;
    35. line-height: 35px;
    36. margin-right: 10px;
    37. }
    38. .breadcrumb {
    39. font-size: 16px;
    40. color: gray;
    41. }
    42. .table {
    43. width: 100%;
    44. text-align: left;
    45. border-radius: 2px 2px 0 0;
    46. border-collapse: separate;
    47. border-spacing: 0;
    48. }
    49. .th {
    50. color: rgba(0, 0, 0, 0.85);
    51. font-weight: 500;
    52. text-align: left;
    53. background: #fafafa;
    54. border-bottom: 1px solid #f0f0f0;
    55. transition: background 0.3s ease;
    56. }
    57. .th.num-th {
    58. flex: 1.5;
    59. }
    60. .th {
    61. text-align: center;
    62. }
    63. .th:nth-child(4),
    64. .th:nth-child(5),
    65. .th:nth-child(6),
    66. .th:nth-child(7) {
    67. text-align: center;
    68. }
    69. .th.th-pic {
    70. flex: 1.3;
    71. }
    72. .th:nth-child(6) {
    73. flex: 1.3;
    74. }
    75. .th,
    76. .td {
    77. position: relative;
    78. padding: 16px 16px;
    79. overflow-wrap: break-word;
    80. flex: 1;
    81. }
    82. .pick-td {
    83. font-size: 14px;
    84. }
    85. .main,
    86. .empty {
    87. border: 1px solid #f0f0f0;
    88. margin-top: 10px;
    89. }
    90. .tr {
    91. display: flex;
    92. cursor: pointer;
    93. border-bottom: 1px solid #ebeef5;
    94. }
    95. .tr.active {
    96. background-color: #f5f7fa;
    97. }
    98. .td {
    99. display: flex;
    100. justify-content: center;
    101. align-items: center;
    102. }
    103. .table img {
    104. width: 100px;
    105. height: 100px;
    106. }
    107. button {
    108. outline: 0;
    109. box-shadow: none;
    110. color: #fff;
    111. background: #d9363e;
    112. border-color: #d9363e;
    113. color: #fff;
    114. background: #d9363e;
    115. border-color: #d9363e;
    116. line-height: 1.5715;
    117. position: relative;
    118. display: inline-block;
    119. font-weight: 400;
    120. white-space: nowrap;
    121. text-align: center;
    122. background-image: none;
    123. border: 1px solid transparent;
    124. box-shadow: 0 2px 0 rgb(0 0 0 / 2%);
    125. cursor: pointer;
    126. transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
    127. -webkit-user-select: none;
    128. -moz-user-select: none;
    129. -ms-user-select: none;
    130. user-select: none;
    131. touch-action: manipulation;
    132. height: 32px;
    133. padding: 4px 15px;
    134. font-size: 14px;
    135. border-radius: 2px;
    136. }
    137. button.pay {
    138. background-color: #3f85ed;
    139. margin-left: 20px;
    140. }
    141. .bottom {
    142. height: 60px;
    143. display: flex;
    144. align-items: center;
    145. justify-content: space-between;
    146. padding-right: 20px;
    147. border: 1px solid #f0f0f0;
    148. border-top: none;
    149. padding-left: 20px;
    150. }
    151. .right-box {
    152. display: flex;
    153. align-items: center;
    154. }
    155. .check-all {
    156. cursor: pointer;
    157. }
    158. .price {
    159. color: hotpink;
    160. font-size: 30px;
    161. font-weight: 700;
    162. }
    163. .price-box {
    164. display: flex;
    165. align-items: center;
    166. }
    167. .empty {
    168. padding: 20px;
    169. text-align: center;
    170. font-size: 30px;
    171. color: #909399;
    172. }
    173. .my-input-number {
    174. display: flex;
    175. }
    176. .my-input-number button {
    177. height: 40px;
    178. color: #333;
    179. border: 1px solid #dcdfe6;
    180. background-color: #f5f7fa;
    181. }
    182. .my-input-number button:disabled {
    183. cursor: not-allowed!important;
    184. }
    185. .my-input-number .my-input__inner {
    186. height: 40px;
    187. width: 50px;
    188. padding: 0;
    189. border: none;
    190. border-top: 1px solid #dcdfe6;
    191. border-bottom: 1px solid #dcdfe6;
    192. }

            inputnumber

    1. .my-input-number {
    2. position: relative;
    3. display: inline-block;
    4. width: 140px;
    5. line-height: 38px;
    6. }
    7. .my-input-number span {
    8. -moz-user-select: none;
    9. -webkit-user-select: none;
    10. -ms-user-select: none;
    11. }
    12. .my-input-number .my-input {
    13. display: block;
    14. position: relative;
    15. font-size: 14px;
    16. width: 100%;
    17. }
    18. .my-input-number .my-input__inner {
    19. -webkit-appearance: none;
    20. background-color: #fff;
    21. background-image: none;
    22. border-radius: 4px;
    23. border: 1px solid #dcdfe6;
    24. box-sizing: border-box;
    25. color: #606266;
    26. display: inline-block;
    27. font-size: inherit;
    28. height: 40px;
    29. line-height: 40px;
    30. outline: none;
    31. padding: 0 15px;
    32. transition: border-color 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);
    33. width: 100%;
    34. padding-left: 50px;
    35. padding-right: 50px;
    36. text-align: center;
    37. }
    38. .my-input-number .my-input-number__decrease,
    39. .my-input-number .my-input-number__increase {
    40. position: absolute;
    41. z-index: 1;
    42. top: 1px;
    43. width: 40px;
    44. height: auto;
    45. text-align: center;
    46. background: #f5f7fa;
    47. color: #606266;
    48. cursor: pointer;
    49. font-size: 13px;
    50. }
    51. .my-input-number .my-input-number__decrease {
    52. left: 1px;
    53. border-radius: 4px 0 0 4px;
    54. border-right: 1px solid #dcdfe6;
    55. }
    56. .my-input-number .my-input-number__increase {
    57. right: 1px;
    58. border-radius: 0 4px 4px 0;
    59. border-left: 1px solid #dcdfe6;
    60. }
    61. .my-input-number .my-input-number__decrease.is-disabled,
    62. .my-input-number .my-input-number__increase.is-disabled {
    63. color: #c0c4cc;
    64. cursor: not-allowed;
    65. }

     图片

    效果图:

  • 相关阅读:
    App买量越来越难,三大增长机遇不容错过
    java.lang.ClassNotFoundException: org.apache.commons.logging.LogFactory 异常错误
    DB2查看索引是否生效
    雷达频带概述及其应用
    windows redis 自启动 Redis服务无法启动报错1067问题
    性能的极致,Rust的加持,Zed-Dev编辑器快速搭建Python3.10开发环境
    Win11鼠标动不了 键盘怎么代替鼠标操作
    【Rust日报】2023-09-07 Tauri 2.0 路线图
    高压放大器在复合视觉的深度测量技术中的应用
    如何防止订单重复支付
  • 原文地址:https://blog.csdn.net/qq_64628470/article/details/133922289