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

也就是说,大家已经看不到官方的代码文件了。
那么既然如此,我们自己写的这个博客记录日志,就显得尤为重要了。继续今天的内容分享。
今天分享的是,添加购物车的第一步操作。
如果用户意见勾选了商品规格,我们就把它按照逻辑业务要求加入购物车内。如果没有选择规格,就给一个提示。
- <script setup>
- import {getDetail} from '@/apis/detail'
- import {ref,onMounted} from 'vue'
- import { useRoute } from 'vue-router';
- import DetailHot from './components/DetailHot.vue'
- import { useCartStore } from '@/stores/cart';
- import { ElMessage } from 'element-plus';
- // import ImageView from '@/components/ImageView/index.vue'
- // import XtxSku from '@/components/XtxSku/index.vue'
- const cartStore = useCartStore()
- const route = useRoute()
- const goods = ref({})
- const getGoods = async ()=>{
- const res = await getDetail(route.params.id)
- goods.value =res.result
- }
- onMounted(()=>getGoods())
- //sku规则被操作时,这里的sku是从子组件内传递过来的数据!
- let skuObj = ref({})
- const skuChange=(sku)=>{
- console.log(sku)
- //赋值。
- skuObj.value = sku
- }
- //count定义好
- const count = ref(1)
- const countChange = (count)=>{
- console.log(count)
- }
- //添加购物车
- const addCart = ()=>{
- if(skuObj.value.skuId){
- //规则已经选择了,触发action
- cartStore.addCart({
- id:goods.value.id,
- name:goods.value.name,
- picture:goods.value.mainPictures[0],
- count:count.value,
- skuId:skuObj.value.skuId,
- attrsText:skuObj.value.specsText,
- selected:true
- })
- }else{
- //规格没有选择,提示用户
- ElMessage.warning('请选择规格')
- }
- }
- </script>
-
- <template>
- <div class="xtx-goods-page">
- <div class="container" v-if="goods.details">
- <div class="bread-container">
- <el-breadcrumb separator=">">
- <el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
- <el-breadcrumb-item :to="{ path: `/category/${goods.categories[1].id}` }">{{goods.categories[1].name}}
- </el-breadcrumb-item>
- <el-breadcrumb-item :to="{ path: `/category/sub/${goods.categories[0].id}` }">{{goods.categories[0].name}}
- </el-breadcrumb-item>
- <el-breadcrumb-item>{{goods.name}}</el-breadcrumb-item>
- </el-breadcrumb>
- </div>
- <!-- 商品信息 -->
- <div class="info-container">
- <div>
- <div class="goods-info">
- <div class="media">
- <!-- 图片预览区 -->
- <XtxImageView :image-list="goods.mainPictures"/>
- <!-- 统计数量 -->
- <ul class="goods-sales">
- <li>
- <p>销量人气</p>
- <p> {{goods.salesCount}}+ </p>
- <p><i class="iconfont icon-task-filling"></i>销量人气</p>
- </li>
- <li>
- <p>商品评价</p>
- <p>{{goods.commentCount}}+</p>
- <p><i class="iconfont icon-comment-filling"></i>查看评价</p>
- </li>
- <li>
- <p>收藏人气</p>
- <p>{{goods.collectCount}}+</p>
- <p><i class="iconfont icon-favorite-filling"></i>收藏商品</p>
- </li>
- <li>
- <p>品牌信息</p>
- <p>{{goods.brand.name}}+</p>
- <p><i class="iconfont icon-dynamic-filling"></i>品牌主页</p>
- </li>
- </ul>
- </div>
- <div class="spec">
- <!-- 商品信息区 -->
- <p class="g-name"> {{goods.name}} </p>
- <p class="g-desc">{{ goods.desc }} </p>
- <p class="g-price">
- <span>{{ goods.price }}</span>
- <span> {{ goods.oldPrice }}</span>
- </p>
- <div class="g-service">
- <dl>
- <dt>促销</dt>
- <dd>12月好物放送,App领券购买直降120元</dd>
- </dl>
- <dl>
- <dt>服务</dt>
- <dd>
- <span>无忧退货</span>
- <span>快速退款</span>
- <span>免费包邮</span>
- <a href="javascript:;">了解详情</a>
- </dd>
- </dl>
- </div>
- <!-- sku组件 -->
- <XtxSku :goods="goods" @change="skuChange"/>
- <!-- 数据组件 -->
- <el-input-number v-model="count" @change="countChange"/>
- <!-- 按钮组件 -->
- <div>
- <el-button size="large" class="btn" @click="addCart">
- 加入购物车
- </el-button>
- </div>
-
- </div>
- </div>
- <div class="goods-footer">
- <div class="goods-article">
- <!-- 商品详情 -->
- <div class="goods-tabs">
- <nav>
- <a>商品详情</a>
- </nav>
- <div class="goods-detail">
- <!-- 属性 -->
- <ul class="attrs">
- <li v-for="item in goods.details.properties" :key="item.value">
- <span class="dt">{{ item.name }}</span>
- <span class="dd">{{item.value}}</span>
- </li>
- </ul>
- <!-- 图片 -->
- <img v-for="img in goods.details.pictures" v-img-lazy="img" :key="img"/>
- </div>
- </div>
- </div>
- <!-- 24热榜+专题推荐 -->
- <div class="goods-aside">
- <!--24小时热榜-->
- <DetailHot :hot-type="1"/>
- <!--每周热榜-->
- <DetailHot :hot-type="2"/>
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
- </template>
-
-
- <style scoped lang='scss'>
- .xtx-goods-page {
- .goods-info {
- min-height: 600px;
- background: #fff;
- display: flex;
-
- .media {
- width: 580px;
- height: 600px;
- padding: 30px 50px;
- }
-
- .spec {
- flex: 1;
- padding: 30px 30px 30px 0;
- }
- }
-
- .goods-footer {
- display: flex;
- margin-top: 20px;
-
- .goods-article {
- width: 940px;
- margin-right: 20px;
- }
-
- .goods-aside {
- width: 280px;
- min-height: 1000px;
- }
- }
-
- .goods-tabs {
- min-height: 600px;
- background: #fff;
- }
-
- .goods-warn {
- min-height: 600px;
- background: #fff;
- margin-top: 20px;
- }
-
- .number-box {
- display: flex;
- align-items: center;
-
- .label {
- width: 60px;
- color: #999;
- padding-left: 10px;
- }
- }
-
- .g-name {
- font-size: 22px;
- }
-
- .g-desc {
- color: #999;
- margin-top: 10px;
- }
-
- .g-price {
- margin-top: 10px;
-
- span {
- &::before {
- content: "¥";
- font-size: 14px;
- }
-
- &:first-child {
- color: $priceColor;
- margin-right: 10px;
- font-size: 22px;
- }
-
- &:last-child {
- color: #999;
- text-decoration: line-through;
- font-size: 16px;
- }
- }
- }
-
- .g-service {
- background: #f5f5f5;
- width: 500px;
- padding: 20px 10px 0 10px;
- margin-top: 10px;
-
- dl {
- padding-bottom: 20px;
- display: flex;
- align-items: center;
-
- dt {
- width: 50px;
- color: #999;
- }
-
- dd {
- color: #666;
-
- &:last-child {
- span {
- margin-right: 10px;
-
- &::before {
- content: "•";
- color: $xtxColor;
- margin-right: 2px;
- }
- }
-
- a {
- color: $xtxColor;
- }
- }
- }
- }
- }
-
- .goods-sales {
- display: flex;
- width: 400px;
- align-items: center;
- text-align: center;
- height: 140px;
-
- li {
- flex: 1;
- position: relative;
-
- ~li::after {
- position: absolute;
- top: 10px;
- left: 0;
- height: 60px;
- border-left: 1px solid #e4e4e4;
- content: "";
- }
-
- p {
- &:first-child {
- color: #999;
- }
-
- &:nth-child(2) {
- color: $priceColor;
- margin-top: 10px;
- }
-
- &:last-child {
- color: #666;
- margin-top: 10px;
-
- i {
- color: $xtxColor;
- font-size: 14px;
- margin-right: 2px;
- }
-
- &:hover {
- color: $xtxColor;
- cursor: pointer;
- }
- }
- }
- }
- }
- }
-
- .goods-tabs {
- min-height: 600px;
- background: #fff;
-
- nav {
- height: 70px;
- line-height: 70px;
- display: flex;
- border-bottom: 1px solid #f5f5f5;
-
- a {
- padding: 0 40px;
- font-size: 18px;
- position: relative;
-
- >span {
- color: $priceColor;
- font-size: 16px;
- margin-left: 10px;
- }
- }
- }
- }
-
- .goods-detail {
- padding: 40px;
-
- .attrs {
- display: flex;
- flex-wrap: wrap;
- margin-bottom: 30px;
-
- li {
- display: flex;
- margin-bottom: 10px;
- width: 50%;
-
- .dt {
- width: 100px;
- color: #999;
- }
-
- .dd {
- flex: 1;
- color: #666;
- }
- }
- }
-
- >img {
- width: 100%;
- }
- }
-
- .btn {
- margin-top: 20px;
-
- }
-
- .bread-container {
- padding: 25px 0;
- }
- </style>
其他的代码辅助有:1-carStore,这是pina的内容。实现数据复用的效果。
我们还做了浏览器缓存同步存储,防止页面刷新引起的数据丢失的情况发生。
1:carStore的内容如下:
- import { ref } from 'vue'
- import { defineStore } from 'pinia'
- export const useCartStore =defineStore('cart',()=>{
- const cartList = ref([])
- const addCart = (goods)=>{
- //添加购物车操作
- //如果已经添加过了,count++
- //没有添加过,直接push
- //s思路:通过匹配传递过来的商品对象的中的skuId能不能在cartList中找到,
- const item = cartList.value.find((item)=>goods.skuId === item.skuId)
- if(item){
- //找到了
- item.count++
- }else{
- cartList.value.push(goods)
- }
- }
- return{
- cartList,
- addCart
- }
- },{
- //同步存储到缓存中,刷新浏览器就不会丢失数据了
- persist: true,
- })
自己登录测试用户后,添加一下购物车,我这边亲自测试了一下,正常的
