【3D商城】使用Vuex状态管理完成购物车模块

创建购物车的全局数据

在这里插入图片描述
在store的index.js中 ,创建购物车变量

  state() {
    return {
      count: 0,
      isFullscreen: false,  //默认不是全屏状态
      buycarts: [],     //购物车变量
    };
  }

添加产品到购物车

 mutations: {
    addBuycarts(state, payload) {      //添加产品到购物车
      state.buycarts.push(payload);
    },
    addBuycartsNum(state, payload) {   //添加购物车商品的数量
      state.buycarts[payload].num++;
    },
    minusBuycartsNum(state, payload) {  //减少购物车商品数量
    state.buycarts[payload].num--;
    	if (state.buycarts[payload].num == 0) {
    	state.buycarts.splice(payload, 1);
      }
    }
 }

计算总价

  getters: {
    totalPrice(state) {
      let total = state.buycarts.reduce((pre, item) => {
        return pre + item.price * item.num;
      }, 0);
      return total;
    },
  }

产品页面组件 添加商品

           <div class="products">
        <div
          class="prod-item"
          :class="{ active: pI == data.pIndex }" //判断现在的索引值是否为选中索引值相同,相同active为true
          v-for="(prod, pI) in data.products"
          @click="changeModel(prod, pI)"
        >
          <div class="prod-title">
            {{ prod.title }}
          </div>
          <div class="img">
            <img :src="prod.imgsrc" :alt="prod.title" />
          </div>
          <a-button type="primary" block @click.stop="addBuycart(prod)">
            <template #icon>
              <ShoppingCartOutlined></ShoppingCartOutlined>
            </template>
            加入购物车
          </a-button>
 </div>

事件后面添加.stop可以在点击填入购物车后,阻止触发changeModel()函数,阻止向上传递,@click.stop="addBuycart(prod)"
调用addBuycart()方法

function addBuycart(prod) {
  let product = { ...prod, num: 1 };  //解构产品并初始化数量为1
  let index = 0;
  let isExist = store.state.buycarts.some((item, i) => {
    if (product.id == item.id) {
      index = i;
      return true;
    } else {
      return false;
    }
  });
  if (isExist) {
    store.commit("addBuycartsNum", index);  //提交
  } else {
    store.commit("addBuycarts", product);
  }
}

导航栏的购物车模块

左侧列表的产品数据会传递到Header中的购物车列表中,并计算总价

<a-menu-item-group title="购物商品">
          <a-menu-item v-for="(item, i) in store.state.buycarts" :key="item.id">
            <div class="prod-item">
              <div class="left">
                <img :src="item.imgsrc" :alt="item.title" />
              </div>
              <div class="middle">
                <div class="title">{{ item.title }}</div>
                <div class="content">
                  <span class="num">数量:{{ item.num }}</span>
                  <div class="control">
                    <span
                      class="btn"
                      @click.stop="store.commit('addBuycartsNum', i)"
                      >+</span
                    >
                    <span
                      class="btn"
                      @click.stop="store.commit('minusBuycartsNum', i)"
                      >-</span
                    >
                  </div>
                </div>
              </div>
              <div class="right">
                <div class="price">¥ {{ item.price * item.num }}</div>
              </div>
            </div>
          </a-menu-item>
          <a-menu-item key="totalPrice">
            <div class="total">
              <span>总价:</span>
              <span class="num"> ¥ {{ store.getters.totalPrice }}</span>
            </div>
          </a-menu-item>
        </a-menu-item-group>

左边是图片、中间是内容(产品的名称、数量、按钮)、右边是产品价格下面是总价,对图片的大小按钮,进行调整 ,购物车的内容一般不会在Product一个组件中显示,全局数据写在App组件中,样式如下:

.ant-menu-submenu {
  z-index: 1000000000 !important;    //优先级最高
}

body .ant-menu-sub .ant-menu-item {
  height: auto;                      //高度自动随着盒子变化
}
.ant-menu-sub .ant-menu-item .prod-item {
  display: flex;
  width: 400px;
  justify-content: space-between;
}
.ant-menu .prod-item img {          //图片
  width: 100px;
  height: 100px;
}
.ant-menu-item .prod-item .middle {   //中间分布
  width: 220px;
  height: 100px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;    // 两边靠
}

.ant-menu-item .prod-item .middle .title {
  font-size: 16px;
  font-weight: 900;
}
.ant-menu-item .prod-item .middle .content {   
  display: flex;
  justify-content: space-between;
}
.ant-menu-item .prod-item .middle .btn {   //按钮
  display: inline-block;
  width: 30px;
  height: 30px;
  text-align: center;
  line-height: 30px;
  border: 1px solid #ccc;
  margin: 0 5px;
}  
.ant-menu-item .prod-item .right .price {  //价格
  font-weight: 900;
  color: orange;
  font-size: 16px;
  display: flex;
  justify-content: center;
  align-items: center;
}
.ant-menu-item .total {               //总价
  font-weight: 900;
  display: flex;
  justify-content: flex-end;
  font-size: 16px;
}
.ant-menu-item .total .num {
  color: orange;
  padding-right: 20px;
}

结果

最终结果显示如下:
点击左侧商品按钮会在导航栏显示,增加各种商品的数量,总价会随着数量一起改变
在这里插入图片描述

常见问题总结

连续点击左侧的添加购物车时,导航栏的购物车模块会添加多个产品,如果是同一件商品,其实只要改变数量即可,问题如下
在这里插入图片描述
需要在addBuycart()方法中增加一个判断,判断添加的产品是否已经存在,some()用来检测是否有满足条件,判断当前选中的产品的id是否和购物车中任何一个产品的id重复,如果重复则只增加数量,不重复则增加商品

  let index = 0;
  let isExist = store.state.buycarts.some((item, i) => {
    if (product.id == item.id) {
      index = i;
      return true;
    } else {
      return false;
    }
  });
  if (isExist) {
    store.commit("addBuycartsNum", index);
  } else {
    store.commit("addBuycarts", product);
  }
  • 9
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值