• vue3前端开发-小兔鲜项目-添加购物车操作第一步


    首先,呢,告诉大家一个坏消息,官方媒体的案例代码已经被他们删除了。如图所示。

    也就是说,大家已经看不到官方的代码文件了。

    那么既然如此,我们自己写的这个博客记录日志,就显得尤为重要了。继续今天的内容分享。

    今天分享的是,添加购物车的第一步操作。

    如果用户意见勾选了商品规格,我们就把它按照逻辑业务要求加入购物车内。如果没有选择规格,就给一个提示。


    1. <script setup>
    2. import {getDetail} from '@/apis/detail'
    3. import {ref,onMounted} from 'vue'
    4. import { useRoute } from 'vue-router';
    5. import DetailHot from './components/DetailHot.vue'
    6. import { useCartStore } from '@/stores/cart';
    7. import { ElMessage } from 'element-plus';
    8. // import ImageView from '@/components/ImageView/index.vue'
    9. // import XtxSku from '@/components/XtxSku/index.vue'
    10. const cartStore = useCartStore()
    11. const route = useRoute()
    12. const goods = ref({})
    13. const getGoods = async ()=>{
    14. const res = await getDetail(route.params.id)
    15. goods.value =res.result
    16. }
    17. onMounted(()=>getGoods())
    18. //sku规则被操作时,这里的sku是从子组件内传递过来的数据!
    19. let skuObj = ref({})
    20. const skuChange=(sku)=>{
    21. console.log(sku)
    22. //赋值。
    23. skuObj.value = sku
    24. }
    25. //count定义好
    26. const count = ref(1)
    27. const countChange = (count)=>{
    28. console.log(count)
    29. }
    30. //添加购物车
    31. const addCart = ()=>{
    32. if(skuObj.value.skuId){
    33. //规则已经选择了,触发action
    34. cartStore.addCart({
    35. id:goods.value.id,
    36. name:goods.value.name,
    37. picture:goods.value.mainPictures[0],
    38. count:count.value,
    39. skuId:skuObj.value.skuId,
    40. attrsText:skuObj.value.specsText,
    41. selected:true
    42. })
    43. }else{
    44. //规格没有选择,提示用户
    45. ElMessage.warning('请选择规格')
    46. }
    47. }
    48. </script>
    49. <template>
    50. <div class="xtx-goods-page">
    51. <div class="container" v-if="goods.details">
    52. <div class="bread-container">
    53. <el-breadcrumb separator=">">
    54. <el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
    55. <el-breadcrumb-item :to="{ path: `/category/${goods.categories[1].id}` }">{{goods.categories[1].name}}
    56. </el-breadcrumb-item>
    57. <el-breadcrumb-item :to="{ path: `/category/sub/${goods.categories[0].id}` }">{{goods.categories[0].name}}
    58. </el-breadcrumb-item>
    59. <el-breadcrumb-item>{{goods.name}}</el-breadcrumb-item>
    60. </el-breadcrumb>
    61. </div>
    62. <!-- 商品信息 -->
    63. <div class="info-container">
    64. <div>
    65. <div class="goods-info">
    66. <div class="media">
    67. <!-- 图片预览区 -->
    68. <XtxImageView :image-list="goods.mainPictures"/>
    69. <!-- 统计数量 -->
    70. <ul class="goods-sales">
    71. <li>
    72. <p>销量人气</p>
    73. <p> {{goods.salesCount}}+ </p>
    74. <p><i class="iconfont icon-task-filling"></i>销量人气</p>
    75. </li>
    76. <li>
    77. <p>商品评价</p>
    78. <p>{{goods.commentCount}}+</p>
    79. <p><i class="iconfont icon-comment-filling"></i>查看评价</p>
    80. </li>
    81. <li>
    82. <p>收藏人气</p>
    83. <p>{{goods.collectCount}}+</p>
    84. <p><i class="iconfont icon-favorite-filling"></i>收藏商品</p>
    85. </li>
    86. <li>
    87. <p>品牌信息</p>
    88. <p>{{goods.brand.name}}+</p>
    89. <p><i class="iconfont icon-dynamic-filling"></i>品牌主页</p>
    90. </li>
    91. </ul>
    92. </div>
    93. <div class="spec">
    94. <!-- 商品信息区 -->
    95. <p class="g-name"> {{goods.name}} </p>
    96. <p class="g-desc">{{ goods.desc }} </p>
    97. <p class="g-price">
    98. <span>{{ goods.price }}</span>
    99. <span> {{ goods.oldPrice }}</span>
    100. </p>
    101. <div class="g-service">
    102. <dl>
    103. <dt>促销</dt>
    104. <dd>12月好物放送,App领券购买直降120</dd>
    105. </dl>
    106. <dl>
    107. <dt>服务</dt>
    108. <dd>
    109. <span>无忧退货</span>
    110. <span>快速退款</span>
    111. <span>免费包邮</span>
    112. <a href="javascript:;">了解详情</a>
    113. </dd>
    114. </dl>
    115. </div>
    116. <!-- sku组件 -->
    117. <XtxSku :goods="goods" @change="skuChange"/>
    118. <!-- 数据组件 -->
    119. <el-input-number v-model="count" @change="countChange"/>
    120. <!-- 按钮组件 -->
    121. <div>
    122. <el-button size="large" class="btn" @click="addCart">
    123. 加入购物车
    124. </el-button>
    125. </div>
    126. </div>
    127. </div>
    128. <div class="goods-footer">
    129. <div class="goods-article">
    130. <!-- 商品详情 -->
    131. <div class="goods-tabs">
    132. <nav>
    133. <a>商品详情</a>
    134. </nav>
    135. <div class="goods-detail">
    136. <!-- 属性 -->
    137. <ul class="attrs">
    138. <li v-for="item in goods.details.properties" :key="item.value">
    139. <span class="dt">{{ item.name }}</span>
    140. <span class="dd">{{item.value}}</span>
    141. </li>
    142. </ul>
    143. <!-- 图片 -->
    144. <img v-for="img in goods.details.pictures" v-img-lazy="img" :key="img"/>
    145. </div>
    146. </div>
    147. </div>
    148. <!-- 24热榜+专题推荐 -->
    149. <div class="goods-aside">
    150. <!--24小时热榜-->
    151. <DetailHot :hot-type="1"/>
    152. <!--每周热榜-->
    153. <DetailHot :hot-type="2"/>
    154. </div>
    155. </div>
    156. </div>
    157. </div>
    158. </div>
    159. </div>
    160. </template>
    161. <style scoped lang='scss'>
    162. .xtx-goods-page {
    163. .goods-info {
    164. min-height: 600px;
    165. background: #fff;
    166. display: flex;
    167. .media {
    168. width: 580px;
    169. height: 600px;
    170. padding: 30px 50px;
    171. }
    172. .spec {
    173. flex: 1;
    174. padding: 30px 30px 30px 0;
    175. }
    176. }
    177. .goods-footer {
    178. display: flex;
    179. margin-top: 20px;
    180. .goods-article {
    181. width: 940px;
    182. margin-right: 20px;
    183. }
    184. .goods-aside {
    185. width: 280px;
    186. min-height: 1000px;
    187. }
    188. }
    189. .goods-tabs {
    190. min-height: 600px;
    191. background: #fff;
    192. }
    193. .goods-warn {
    194. min-height: 600px;
    195. background: #fff;
    196. margin-top: 20px;
    197. }
    198. .number-box {
    199. display: flex;
    200. align-items: center;
    201. .label {
    202. width: 60px;
    203. color: #999;
    204. padding-left: 10px;
    205. }
    206. }
    207. .g-name {
    208. font-size: 22px;
    209. }
    210. .g-desc {
    211. color: #999;
    212. margin-top: 10px;
    213. }
    214. .g-price {
    215. margin-top: 10px;
    216. span {
    217. &::before {
    218. content: "¥";
    219. font-size: 14px;
    220. }
    221. &:first-child {
    222. color: $priceColor;
    223. margin-right: 10px;
    224. font-size: 22px;
    225. }
    226. &:last-child {
    227. color: #999;
    228. text-decoration: line-through;
    229. font-size: 16px;
    230. }
    231. }
    232. }
    233. .g-service {
    234. background: #f5f5f5;
    235. width: 500px;
    236. padding: 20px 10px 0 10px;
    237. margin-top: 10px;
    238. dl {
    239. padding-bottom: 20px;
    240. display: flex;
    241. align-items: center;
    242. dt {
    243. width: 50px;
    244. color: #999;
    245. }
    246. dd {
    247. color: #666;
    248. &:last-child {
    249. span {
    250. margin-right: 10px;
    251. &::before {
    252. content: "•";
    253. color: $xtxColor;
    254. margin-right: 2px;
    255. }
    256. }
    257. a {
    258. color: $xtxColor;
    259. }
    260. }
    261. }
    262. }
    263. }
    264. .goods-sales {
    265. display: flex;
    266. width: 400px;
    267. align-items: center;
    268. text-align: center;
    269. height: 140px;
    270. li {
    271. flex: 1;
    272. position: relative;
    273. ~li::after {
    274. position: absolute;
    275. top: 10px;
    276. left: 0;
    277. height: 60px;
    278. border-left: 1px solid #e4e4e4;
    279. content: "";
    280. }
    281. p {
    282. &:first-child {
    283. color: #999;
    284. }
    285. &:nth-child(2) {
    286. color: $priceColor;
    287. margin-top: 10px;
    288. }
    289. &:last-child {
    290. color: #666;
    291. margin-top: 10px;
    292. i {
    293. color: $xtxColor;
    294. font-size: 14px;
    295. margin-right: 2px;
    296. }
    297. &:hover {
    298. color: $xtxColor;
    299. cursor: pointer;
    300. }
    301. }
    302. }
    303. }
    304. }
    305. }
    306. .goods-tabs {
    307. min-height: 600px;
    308. background: #fff;
    309. nav {
    310. height: 70px;
    311. line-height: 70px;
    312. display: flex;
    313. border-bottom: 1px solid #f5f5f5;
    314. a {
    315. padding: 0 40px;
    316. font-size: 18px;
    317. position: relative;
    318. >span {
    319. color: $priceColor;
    320. font-size: 16px;
    321. margin-left: 10px;
    322. }
    323. }
    324. }
    325. }
    326. .goods-detail {
    327. padding: 40px;
    328. .attrs {
    329. display: flex;
    330. flex-wrap: wrap;
    331. margin-bottom: 30px;
    332. li {
    333. display: flex;
    334. margin-bottom: 10px;
    335. width: 50%;
    336. .dt {
    337. width: 100px;
    338. color: #999;
    339. }
    340. .dd {
    341. flex: 1;
    342. color: #666;
    343. }
    344. }
    345. }
    346. >img {
    347. width: 100%;
    348. }
    349. }
    350. .btn {
    351. margin-top: 20px;
    352. }
    353. .bread-container {
    354. padding: 25px 0;
    355. }
    356. </style>

    其他的代码辅助有:1-carStore,这是pina的内容。实现数据复用的效果。

    我们还做了浏览器缓存同步存储,防止页面刷新引起的数据丢失的情况发生。


    1:carStore的内容如下:

    1. import { ref } from 'vue'
    2. import { defineStore } from 'pinia'
    3. export const useCartStore =defineStore('cart',()=>{
    4. const cartList = ref([])
    5. const addCart = (goods)=>{
    6. //添加购物车操作
    7. //如果已经添加过了,count++
    8. //没有添加过,直接push
    9. //s思路:通过匹配传递过来的商品对象的中的skuId能不能在cartList中找到,
    10. const item = cartList.value.find((item)=>goods.skuId === item.skuId)
    11. if(item){
    12. //找到了
    13. item.count++
    14. }else{
    15. cartList.value.push(goods)
    16. }
    17. }
    18. return{
    19. cartList,
    20. addCart
    21. }
    22. },{
    23. //同步存储到缓存中,刷新浏览器就不会丢失数据了
    24. persist: true,
    25. })

    自己登录测试用户后,添加一下购物车,我这边亲自测试了一下,正常的

  • 相关阅读:
    手机蓝牙调试助手,设置红绿灯时间,本次设置红灯28s,绿灯24s,其中红绿灯时间可以任意设置,最大值四位数之内,是智慧城市交通灯联网Ai调控前期探索。
    Leetcode-每日一题1106. 解析布尔表达式(DFS模拟栈)
    Redis 技术整理
    springboot+个人博客 毕业设计-附源码191613
    C++ 学习 之 成员指针
    Microsoft Outlook Lite 引入短信功能
    深入学习JVM底层(三):垃圾回收器与内存分配策略
    高德API JS 高德地图获取多个坐标点的中心点
    数据存储,详细讲解
    Spring Cloud Alibaba 工程搭建连接数据库
  • 原文地址:https://blog.csdn.net/yrldjsbk/article/details/141067517