Vuex实现购物车功能

Vuex实现购物车功能(附:效果视频)

功能描述:

  • 加购
  • 删除
  • 加减
  • 全选反选
  • 选中计算总价
  • 存储

整体演示效果如下:

在这里插入图片描述
首先介绍一下Vuex:

Vuex 实例对象属性 主要有下面5个核心属性:

state : 全局访问的state对象,存放要设置的初始状态名及值(必须要有)

mutations : 里面可以存放改变 state 的初始值的方法 ( 同步操作–必须要有 )

getters: 实时监听state值的变化可对状态进行处理,返回一个新的状态,相当于store的计算属性(不是必须的)

actions : 里面可以存放用来异步触发 mutations 里面的方法的方法 ( 异步操作–不是必须的 )

modules : 存放模块化的数据(不是必须的)

一、主页面Home:

<template>
   <div id="app">
      <div class="nav-top">
         <!--      标签栏-->
         <van-nav-bar
               title="商品列表页"
               left-arrow
         />
      </div>
      <div class="nav-bottom">
         <!--      商品卡片-->
         <van-card
               v-for="item in goodsList"
               :price="item.actualPrice"
               :desc="item.desc"
               :title="item.dtitle"
               :thumb="item.mainPic"
         >
            <template #num>
               <van-icon name="shopping-cart-o" color="red" size="24px" @click="add(item)"/>
            </template>
         </van-card>
      </div>
   </div>
</template>

<script>

   export default {
      data() {
         return {
            goodsList: [], // 商品列表数据
         }
      },
      //  请求商品列表数据
      mounted() {
       // 接口不予展示,有需要请自行下载
         this.$axios.get('api接口').then(res => {
            this.goodsList = res.data.data.data
            // console.log(this.goodsList)
         })
      },
      methods: {
         // 添加商品  调用vuex中的add方法
         add(item) {
            this.$store.commit('add', item)
         }
      }
   }
</script>

<style lang="scss" scoped>
   #app {
      .nav-top {
         width: 100%;
         position: fixed;
         top: 0;
         left: 0;
         z-index: 9;
      }
      .nav-bottom {
         margin-top: 50px;
      }
   }
</style>

二、购物车页面ShopCart:

<template>
   <div>
      <!--      标签栏-->
      <van-nav-bar
            title="购物车"
            left-arrow
            @click-left="back"
      />
      <!--     购物车box -->
      <div class="car-box" v-for="(item,index) in list" :key="index">
         <!--   左侧复选框布局-->
         <div class="car-box-left">
            <van-checkbox v-model="item.ckd"></van-checkbox>
         </div>
         <!--   右侧商品卡片布局-->
         <div class="car-box-right">
            <van-swipe-cell>
               <van-card
                     :price="item.item.actualPrice"
                     :title="item.item.dtitle"
                     :thumb="item.item.mainPic"
               >
                  <!--  步进器-->
                  <template #num>
                     <van-stepper v-model="item.num" theme="round" button-size="22" disable-input
                                  @change="changeNum(item.num)"/>
                  </template>
               </van-card>
               <!--     右侧滑动删除-->
               <template #right>
                  <van-button square text="删除" type="danger" class="delete-button" @click="del(index)"/>
               </template> 
            </van-swipe-cell>
         </div>
      </div>
      <!--   空状态  没数据显示 有数据隐藏-->
      <van-empty
            v-show="$store.state.cartList.length==0"
            class="custom-image"
            image="https://img.yzcdn.cn/vant/custom-empty-image.png"
            description="购物车是空的哟!"
      />
      <!--      商品导航-->
      <van-submit-bar :price="$store.getters.total*100" button-text="提交订单">
         <van-checkbox v-model="checkAll">全选</van-checkbox>
      </van-submit-bar>

   </div>
</template>

<script>
   import {mapMutations} from 'vuex'
   export default {
      data() {
         return {
            list: this.$store.state.cartList, //购物车数据
         }
      },
      computed: {
         // 计算属性checkAll 和全选按钮双向数据绑定,别人可以控制它 它也可以控制别人
         // 别人控制它 给他一个值的时候是 get , 它控制别人 给别人设置值的时候 是set
         // 在set中newVal参数是这个计算属性改变后的值
         checkAll: {  //可以看作一个事件
            get() {
               //  判断购物车里商品的长度为0  return false
               if (this.list.length == 0) {
                  return false
               }
               return this.$store.state.cartList.every(item => {
                  return item.ckd == true   // 返回结果复选框为true
               })
            },
            set(newVal) {
               this.$store.commit('ckd', newVal)
            },
         }
      },
      methods: {
         // 返回商品列表页
         back() {
            this.$router.push({
               path: '/'
            })
         },
           //方法集合
         ...mapMutations(['del', 'changeNum',])
      },
   }
</script>

<style lang="scss" scoped>
   .goods-card {
      margin: 0;
      background-color: white;
   }
   .delete-button {
      height: 100%;
   }
   .car-box {
      width: 100%;
      margin-bottom: 5px;
      display: flex;
      flex-wrap: nowrap;
      align-items: center;
      .car-box-left {
         flex: 1;
         padding-left: 10px;
      }
      .car-box-right {
         flex: 12;
      }
   }
</style>

三、Vuex代码:

import Vue from 'vue'
import Vuex from 'vuex'
import VuexPersist from 'vuex-persist'

Vue.use(Vuex);

export default new Vuex.Store({
   state: {
      cartList: [], // 购物车数据
   },
   mutations: {
      // 添加商品
      add(state, item) {
         // console.log(item)
         let flag = false;
         // 加购去重(通过id判断)
         state.cartList.forEach(i => {
            if (i.item.id == item.id) {
               i.num++;
               flag = true;
            }
         })
         if (flag == false) {
            state.cartList.push({
               num: 1,  // 添加数量默认为1
               item,  // 添加购物车商品数据
               ckd: false,  // 添加复选框初始化状态为false
            })
         }
         // console.log(state.cartList)
      },
      // 删除商品
      del(state, index) {
         state.cartList.splice(index, 1)
         // state.
      },
      // 改变数量------加减综合法   !!!
      changeNum(state, index) {
         state.cartList.num = index
      },
      //  全选全不选
      ckd(state, newAll) {
         state.cartList.forEach(item => {
            item.ckd = newAll
         })
      }

   },
   //  计算 getters
   getters: {
      // 总价
      total(state) {
         let sum = 0;
         state.cartList.forEach(item => {
            //  如果复选框选中   计算总价
            if (item.ckd == true) {
               sum += item.item.actualPrice * item.num
            }
         })
         return sum
      }
   },
   actions: {},
   modules: {},
   // Vuex存储插件
   plugins: [
      new VuexPersist({
         storage: window.localStorage,
      }).plugin,
   ]
})
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值