首页 > 技术文章 > 商品加入购物车,vuex 管理状态

Console-LIJIE 2020-02-21 14:51 原文

商品加入购物车,保存在store中。大概一下步骤:

1.实现点击加入购物车功能;

2.徽标数值的自动更新;

3.购物车商品的本地持久存储;

4.获取购物车商品并加载显示;

5.加载显示购物车列表时初始化numbox数量值;

6.实现购物车商品数量改变同步到store中;

7.购物车中商品的删除;

8.把store中商品的选中状态selected同步到页面上;

9.同步shopcar页面商品选中状态到store中保存;

10.勾选商品的总价和数量自动计算

一、将商品加入保存到store中

<mt-button type="danger" size="small" @click="addToShopCar">加入购物车</mt-button>

拼接出一个对象,通过传参的形式,传给mutations中的方法,其中 numBoxCount 为 numbox 的值,即加入购物车的商品数,通过子组件调用父组件的方法,将值传给父组件得来;

 1 //  添加至购物车
 2         addToShopCar(){
 3           this.ballFlag = !this.ballFlag;
 4 
 5         //  拼接出一个商品对象保存到store中、{id:商品id,count:要购买的数量,price:商品价格,selected:false}
 6           const YHHSelectShop = {
 7             id:this.id,
 8             count:this.numBoxCount,
 9             price:this.youHaoHuo.price,
10             selected:true
11           };
12           this.$store.commit('YHHSelectShopAddToShopCar',YHHSelectShop)
13         }
14       }

在mutations中,将商品存入到 localStorage中持久化,

 1   YHHSelectShopAddToShopCar(state,YHHSelectShop) {
 2 
 3     // 假设购物车中没有找到
 4     var flag = false;
 5 
 6     state.shopCar.some(item => {
 7       if (item.id == YHHSelectShop.id) {
 8         item.count += parseInt(YHHSelectShop.count);
 9         flag = true;
10         return true
11       }
12     });
13     // 最终没有找到,就把商品加入购物车中
14     if (!flag) {
15       state.shopCar.push(YHHSelectShop)
16     }
17     // 存储到 localStorage
18     localStorage.setItem('shopCar',JSON.stringify(state.shopCar))
19   },

然后store再从localStorage中取数据 const shopCarItem = JSON.parse(localStorage.getItem('shopCar') || '[]'); shopCar: shopCarItem 

二、得到徽标数值,getters 中

  // 徽标数值
  getAllSelectShopCount(state){
    var allCount = 0;
    state.shopCar.forEach(item => {
      allCount += item.count
    });
    return allCount
  },

然后去APP.vue 显示徽标数值

      <router-link class="mui-tab-item-my" to="/shopcar">
        <span class="mui-icon mui-icon-extra mui-icon-extra-cart">
          <span class="mui-badge" id="shopCar">{{ $store.getters.getAllSelectShopCount }}</span></span>
        <span class="mui-tab-label">购物车</span>
      </router-link>

三、获取购物车中所有商品列表并加载显示,遍历shopcar中的每件商品得到id,请求数据

 1  // 获取到 store 中所有的商品
 2           async getShopCarList(){
 3             var idArr = [];
 4             var shopId;
 5 
 6             // 从store中拿到购物车中商品的id
 7             this.$store.state.shopCar.forEach(item => idArr.push(item.id));
 8 
 9             // 如果购物车中没有商品,直接返回
10             if (idArr.length === 0) {
11               return
12             }
13             // console.log(idArr)
14             // 循环得到id,分别请求数据
15               for (let i = 0;i < idArr.length;i++){
16 
17                 shopId = parseInt(idArr[i]);
18                 // console.log(typeof (shopId))
19 
20                 if (shopId >= 1 && shopId <= 40) {
21                   const res = await this.$axios.get('/getshoplistshopcar/'+shopId,this.model);
22                   // console.log(res)
23                   if (res.status === 200) {
24                     this.shopCarList = this.shopCarList.concat(res.data)
25                   }
26                 } else if (shopId >= 41 && shopId <= 46) {
27                   const res = await this.$axios.get('/getyouhaohuoshopcar/'+shopId,this.model);
28                   // console.log(res)
29                   if (res.status === 200) {
30                     this.shopCarList = this.shopCarList.concat(res.data)
31                   }
32                 }  else if (shopId >= 50 && shopId <= 139) {
33                   const res = await this.$axios.get('/getyouhaohuoinfoshopcar/'+shopId,this.model);
34                   // console.log(res)
35                   if (res.status === 200) {
36                     this.shopCarList = this.shopCarList.concat(res.data)
37                   }
38                 } else if (shopId >= 140 && shopId <= 229) {
39                   const res = await this.$axios.get('/getaiguangjieinfoshopcar/'+shopId,this.model);
40                   // console.log(res)
41                   if (res.status === 200) {
42                     this.shopCarList = this.shopCarList.concat(res.data)
43                   }
44                 } else if (shopId >= 230 && shopId <= 259) {
45                   const res = await this.$axios.get('/getcainilikeshopcar/'+shopId,this.model);
46                   // console.log(res)
47                   if (res.status === 200) {
48                     this.shopCarList = this.shopCarList.concat(res.data)
49                   }
50                 }
51               }
52             // console.log(this.shopCarList)
53           },

四、shopcar页面numbox的加载显示,getters 中

1   // shopcar 中各个商品的 numbox 值
2   getShopCarSelectCount(state){
3     var shopCarCount = {};
4     state.shopCar.forEach(item => {
5       // 商品的id作为键,数量作为值
6       shopCarCount[item.id] = item.count
7     });
8     return shopCarCount
9   },

然后在shopcar页面,将值传给numbox子组件,子组件通过props接受Count值,

<NumBox 

:Count = "$store.getters.getShopCarSelectCount[item.id]" // 商品件数转给子组件
:shopId = "item.id"  // 商品id传给子组件
></NumBox>

五、shopcar页面numbox改变同步到store中

mutations中

 1   // shopcar 页面修改 numbox
 2   updateShopCarCount(state,selectShop) {
 3     state.shopCar.some(item => {
 4       if (item.id == selectShop.id) {  //  item.id 类型为Number,selectShop.id 类型为string
 5         item.count = parseInt(selectShop.count);
 6         return true
 7       }
 8     });
 9     // 当修改完商品的数量,把最新的数量保存到本地存储中
10     localStorage.setItem('shopCar',JSON.stringify(state.shopCar))
11   }

shopcar-numbox组件中,调用mutations中的方法,将值传给mutations

1  countChanged(){ // 数量改变
2           // console.log(this.$refs.numBox.value)
3           // 每当数量值改变,立即把当前最新的数量同步到 store 中,覆盖之前的数量值
4           this.$store.commit("updateShopCarCount",{
5             id:this.shopId,
6             count:this.$refs.numBox.value
7           })
8         }

六、商品的删除

删两个部分,1.界面的商品数组中;2.store中

shopcar组件中

1    // 取消订单
2         remove(id,index){
3         //    点击删除,把商品从 store 中根据传递的id删除
4         //      同时把当前组件中的 shopCarList 中,对应要删除的那个商品使用index来删除
5           this.shopCarList.splice(index,1);  // 删数组shopCarList中
6 
7           this.$store.commit('removeFromShopCar',id)  // 删store中
8         }

mutations中

 1   //  根据id从store中的购物车中删除对应的数据
 2   removeFromShopCar(state,id) {
 3     state.shopCar.some((item,i) => {
 4       if (item.id == id) {
 5         state.shopCar.splice(i,1);
 6         return true
 7       }
 8     });
 9     localStorage.setItem('shopCar',JSON.stringify(state.shopCar))
10   }

七、store 中商品选中的状态 selected 同步到页面上

getters 中

1   // 商品选中状态
2   getShopCarSelected(state) {
3     var Obj = {};
4     state.shopCar.forEach(item => {
5       Obj[item.id] = item.selected
6     });
7     return Obj
8   },

在shopcar页面switch中

            <mt-switch class="shopCar-switch"
              v-model="$store.getters.getShopCarSelected[item.id]">
            </mt-switch>

八、selected 状态改变同步到store中

mutations 中

1   // 改变商品选中
2   updateShopCarSelected(state,switchInfo) {
3     state.shopCar.some(item => {
4       if (item.id == switchInfo.id) {
5         item.selected = switchInfo.selected
6       }
7     });
8     localStorage.setItem('shopCar',JSON.stringify(state.shopCar))
9   }

shopcar中,将id及状态传给mutations

            <mt-switch class="shopCar-switch"
              v-model="$store.getters.getShopCarSelected[item.id]"
              @change="selectedChange(item.id,$store.getters.getShopCarSelected[item.id])">
            </mt-switch>
1      // 改变商品选中
2         selectedChange(id,newVal) {
3           console.log(id+'---'+newVal)
4           this.$store.commit('updateShopCarSelected',{ id , selected : newVal })
5         }

九、勾选数量和总价的计算

getters中

 1 // 得到 总价 和 总量
 2   getShopCarAllPriceAndCount(state) {
 3     var Obj = {
 4       COUNT:0,  // 勾选的数量
 5       PRICE:0   // 勾选的总价
 6     };
 7     state.shopCar.forEach(item => {
 8       if (item.selected) { // 被勾选
 9         Obj.COUNT += item.count;
10         Obj.PRICE += item.price * item.count
11       }
12     });
13     return Obj
14   }

shopcar页面

              <p>
                已选 <span class="red">{{ $store.getters.getShopCarAllPriceAndCount.COUNT }}</span> 件,总价
                <span class="red">¥{{ $store.getters.getShopCarAllPriceAndCount.PRICE }}</span>(不含运费)
              </p>

 

推荐阅读