VUE+Vuex购物车功能实现

效果图

 在商品详情中设置一个加入购物车的按钮<button>

//goods是需要加入购物车的商品

 <button @click="addToCart(goods)">加入购物车</button>

 methods:{

        //item是一个形参

        addToCart(item){

           //加入购物车

            this.$store.dispatch('addCart',item);

        }

    }

购物车页面布局设计

src/components/Cart.vue创建一个vue文件Cart.vue

<!-- 购物车列表 -->
      <div class="cart">
          <!-- 购物车列表头部 -->
          <ul class="m-inline-block">
              <li class="inline-block item-goods">商品</li>
              <li class="inline-block item-price">价格</li>
              <li class="inline-block item-count">数量</li>
              <li class="inline-block item-operate">操作</li>
          </ul>
          <!-- 标题 -->
          <div class="cart-title">购物车</div>
          <!-- 表身 -->
          <div class="table-box-inner">
              <table>
                   <!-- 遍历商品-->
                  <tr class="vFor" v-for="(item,index) in cartList" :key="index">
                      <td class="item-goods">
                          <!--选中商品-->
                          <input class="goods-input" type="checkbox" :checked=" item.item.checked"  @click="selectItem(item)">
                          <!--商品图片-->
                          <a class="goods-a" href=""><img :src="item.item.img" alt=""></a>                      <!--商品详情-->
                          <div class="goods-info">
                              <h4>{{item.item.detail}}</h4>
                          </div>
                      </td>
                      <!--商品价格-->
                      <td class="item-price">
                          ¥{{item.item.price}}
                      </td>
                      <td class="item-count">
                          <!--加商品-->
                          <button class="btn-add" @click="add(item.item)">+</button>
                          {{item.item.count}}
                          <!--减商品-->
                          <button class="btn-sub" @click="sub(item.item)">-</button>
                      </td>
                      <td class="item-operate">
                          <!--删除商品-->
                          <button class="btn-del" @click="del(index)">{{btnDel}}</button>
                      </td>
                  </tr>
              </table>
          </div>
      </div>
      <!-- 总计 -->
      <div class="totals">
          <div class="total">
              <p>共&nbsp;<em>{{totalNum}}</em>&nbsp;件商品</p>
              <p>总金额&nbsp;<em>¥{{totalPrice}}</em>&nbsp;
                  </p>
          </div>
          <div class="pays" >
              <div class="pay-p pay">请在倒计时结束前结算&nbsp;&nbsp;|
                  &nbsp;&nbsp;总金额&nbsp;<em>¥{{totalPrice}}</em>&nbsp;
              </div>
              <div class="pay-a pay">
                <button @click="topay">立即结算</button>
              </div>
          </div>
      </div>

Cart.vue中的<script>部分

//引入mapGetters

import { mapGetters } from 'vuex';

export default {

      name:'Cart',

      data(){

          return {

      },

      computed:{

        //保存的数据

        //购物车选中结算的总价格和总数量

        ...mapGetters(['totalPrice']),

        ...mapGetters(['totalNum']),

        cartList(){

           //返回购物车中的商品数据

            return this.$store.state.cartList;

        },

      },

      methods:{

        //点击商品的复选框

        selectItem(item){

            this.$store.dispatch("selectItem",item)

        },

        //加商品

         add(item){

           

            this.$store.dispatch("addItem", item);

         },

         //减商品

         sub(item){

            this.$store.dispatch("subItem", item);

         },

         //删除商品

         del(index){

            this.$store.dispatch("delete", index);

         },

      }

  }

  </script>

Cart.vue的CSS样式

 /* 购物车列表 */
  .m-inline-block{
      width: 960px;
      height: 38px;
      border: 1px solid #e0e0e0;
      line-height: 38px;
      background-color: rgb(255,255,255);
      margin: 0 auto;
      position: relative;
  }
  .inline-block{
      display: inline-block;
      text-align: center;
  }
  .item-goods{
      width: 400px;
  }
  .item-price{
      width: 222px;
      text-align: center;
  }
  .item-count{
      width: 162px;
      text-align: center;
  }
  .item-operate{
      width: 174px;
      text-align: center;
  }
  /* 标题 */
  .cart-title{
      width: 930px;
      height: 24px;
      font-size: 16px;
      text-align: left;
      color: #f10180;
      margin: 20px auto;
      position: relative;
  }
  .table-box-inner{
      width: 960px;
      margin: 0 auto;
      position: relative;
      border: 1px solid #ecebeb;
  }
  .vFor{
      height: 100px;
     
      padding-bottom: 10px;
  }
  
  /* 商品 */
  .goods-input,.goods-a,.good-info{
      float: left;
  }
  .goods-input{
      position: relative;
      margin: 30px 10px;
      width: 20px;
      height: 20px;
  }
  .goods-a{
      left: 10px;
      position: relative;
  }
  .goods-a img{
      width: 100px;
      height: 100px;
  }
  .goods-info{
      position: relative;
      left: 20px;
      font-size: 12px;
      width: 200px;
      margin: 0 auto;
  }
  /* 价格 */
  .vFor .item-price{
      color:#f10180;
  }
  /* 操作 */
  
  .btn-sub,.btn-del,.btn-add{
      width: 50px;
      height: 20px;
      border:none;
      background-color:antiquewhite;
  }
  /* 总计 */
  .totals{
      width: 960px;
      height: 150px;
      margin: 0 auto;
      margin-top: 50px;
      position: relative;
      border: 1px solid #ecebeb;
      /* border-bottom: none; */
  }
  .totals .total{
      width: 200px;
      height: 150px;
      left: 760px;
      position: relative;
      text-align: center;
      
  }
  .totals .total p{
      margin-top: 40px;
  }
  em{
      color:#f10180;
  }
  /* 结算 */
  .pays{
      box-sizing: content-box;
      position: fixed;
      width: 960px;
      height: 50px;
      margin: 0 auto;
      border: 1px solid #ecebeb;
      bottom: 0;
     
  }
  .pay{
      height: 50px;
      line-height: 50px;
      float: left;
  }
  .pay-p{
      width: 760px;
      text-align: right;
      background-color: #f3f3f3;
      color: #333;
      padding-right: 30px;
  }
  .pay-a{
      width: 200px;
      text-align: center;
      background-color:#f10180;
  }
  .pay-a button{
      border: none;
      color:#f9f9f9;
      background-color:#f10180;
  }

在store/index.js中

import Vue from "vue";
import Vuex from 'vuex';

Vue.use(Vuex)

//用于响应组件中的动作
const actions = {
    //加入购物车
    addCart(context,item){
        context.commit('ADDCART',item)
        alert("加入购物车成功");
    },
    //复选框
    selectItem(context,item){
        context.commit("SELECTITEM", item);
    },

    //加商品
    addItem(context,item){
        context.commit('ADDITEM',item);
    },
    //减商品
    subItem(context,item){
        context.commit('SUBITEM',item);
    },
     //删除商品
     delete(context,index){
        context.commit('DELETE',index);
    }
};

//用于真正改变数据
const mutations = {
    //加入购物车
    ADDCART(state, item){
        //判断本地是否有数据,默认没有
        let flag = false;

        //遍历在state中的cartList
        state.cartList.map(ele => {
            //判断state保存本地的id和传过来的id是否一样
            
            if(ele.item.id == item.id){
                flag = true;
                ele.item.count++
            }
        })
        console.log('item', item)
        if(!flag){
            state.cartList.push({item})
        }

    },
    //复选框
    SELECTITEM(state, item){
        item.item.checked = !item.item.checked;
    },
    //加商品
    ADDITEM(state,item){
        item.count++;
    },
    //减商品
    SUBITEM(state,item){
        if(item.count > 1){
            item.count--;
       }
    },
    //删除商品
    DELETE(state,index){
        state.cartList.splice(index, 1);
    },
};
     
//用于存放数据
const state = {
    cartList:[],//存放购物车商品数据的数组
    totalPrice:0,
    totalNum: 0, 
};

const getters = {
    totalPrice: state => {
        let totalNum = 0;
        let totalPrice = 0;
        state.cartList.filter(item => {
            if(item.item.checked){
                totalNum ++;
                totalPrice += item.item.count * item.item.price;
            }
        })
        return totalPrice;
    },
    totalNum: state => {
        let totalNum = 0;
        state.cartList.filter(item => {
            if(item.item.checked){
                totalNum += item.item.count;
            }
        })
        return totalNum;
    }
};

export default new Vuex.Store({
    actions,
    mutations,
    state,
    getters
})


版权声明:本文为weixin_57383920原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。