Vue + Vant + Vuex shopping cart functionality for local

Usually, we do mobile end mall, they usually have a shopping cart module, that cart module implemented in two ways, one is stored in the background to get the shopping cart information through the interface, and second, there is a local user's mobile phone, the first as long as the method call interface is relatively simple to obtain, it presented here is the second method, the method will use vuex local presence cart data.

Before vue project creation methods and vuex wording Bowen has introduced, will not repeat it here;

vant installation:

By mounting npm # 
I Vant -S npm 

# mounting yarn by 
yarn add vant

Specific use, please go to its official website to know

Address: https://youzan.github.io/vant/#/zh-CN/

Shopping cart page and write local prices:

1. We demand the introduction of the vant, we use the Icon, Checkbox, Stepper, SubmitBar, Toast these components;

2. In order to facilitate replication that is used, I wrote in the local data of some dead cart goods for rendering;

3. Although there is a local product information is to the shopping cart, in fact, we just need to keep merchandise id and quantity NUM ;

4. We need to radio the change events , select all events , stepper increase decrease were prices converted;

In order to facilitate copying and pasting directly see the effect, directly on the demo

demo.html

<template>
  <div class="shopCart">
    <div class="cartList">
      <ul v-if="goods.length > 0">
        <li v-for="item in goods" :key="item.id">
          <van-checkbox
            :value="item.id"
            v-model="item.isChecked"
            checked-color="#15C481"
            @click="chooseChange(item.id, item)"
          ></van-checkbox>
          <div class="shopdetail">
            <div class="detailimg">
              <img :src="item.thumb" />
            </div>
            <div class="detailtext">
              <div class="shoptitle van-multi-ellipsis--l2">
                {{ item.title }}
              </div>
              <div class="shoppricenum">
                <p class="shopprice">
                  ¥{{ item.price
                  }}{{ item.lvd > 0 ? "+" + item.lvd + "LVD" : "" }}
                </p>
                <div class="shopnum">
                  <van-stepper v-model="item.num" @change="onChange(item)" />
                </div>
              </div>
            </div>
          </div>
        </li>
      </ul>
      <div class="nohaveshop" v-else>
        <van-icon name="shopping-cart-o" />
        <p class="p1">你的购物车空空如也~~</p>
        <p class="p2">快去采购吧!</p>
      </div>
    </div>
    <div class="cartfotter" v-if="goods.length > 0">
      <van-submit-bar button-text="去结算" @submit="onSubmit">
        <van-checkbox
          v-model="allchecked"
          checked-color="#15C481"
          @click="checkAll"
          >全选</van-checkbox
        >
        <div class="buyprice">
          <p class="p1">合计</p>
          <p class="p2">
            ¥{{ totalprice }}{{ totallvd > 0 ? "+" + totallvd + "LVD" : "" }}
          </p>
        </div>
      </van-submit-bar>
    </div>
  </div>
</template>

<script>
import { Icon, Checkbox, Stepper, SubmitBar, Toast } from "vant";
export default {
  components: {
    [Icon.name]: Icon,
    [Checkbox.name]: Checkbox,
    [Stepper.name]: Stepper,
    [SubmitBar.name]: SubmitBar,
    [Toast.name]: Toast
  },
  data() {
    return {
      goods:[
        {
          id: 1,
          title: "Zoneid 2019 new blue cashmere jacket collar male stitching into a new 9.9", 
          . price: 980, 
          LVD: 12, 
          NUM: 1, 
          Thumb: 
            "https://img.yzcdn.cn/public_files/2017/10/ 24 / 2f9a36046449dafb8608e99990b3c205.jpeg "
         } ,
         { 
          ID : 2, 
          title:" young women retro fashion warm jacket lapel stitching ", 
          . price: 1200, 
          LVD: 0, 
          NUM: 2, 
          Thumb: 
            " https://img.yzcdn.cn /public_files/2017/10/24/f6aabd6ac5521195e01e8e89ee9fc63f.jpeg "
         } ,
         { 
          ID : . 3, 
          title:"Mature new men suit jacket and collar perspective splicing dress ", 
          . price: 1000, 
          LVD:. 8, 
          NUM:. 1, 
          Thumb: 
            "https://img.yzcdn.cn/public_files/2017/10/24/320454216bbe9e25c7651e1fa51b31fd. JPEG "
         } 
      ], 
      allchecked: to false, 
      selectedData: [], 
      // total 
      TotalPrice: 0, 
      totallvd: 0 
    }; 
  }, 
  Created: function () { 
    this.count ();
   } , 
  computed: {} , 
  Methods: { 
    // radio change event 
    chooseChange (I, Item) { 
      Toast (I);
      if (this.selectedData.indexOf(i) > -1) {
        console.log(i);
        var arrs = this.selectedData.filter(function(item) {
          return item != i;
        });
        this.selectedData = arrs;
        item.isChecked = false;
        // this.remove(this.selectedData, i);
        this.count();
        console.log(this.selectedData);
      } else {
        this.selectedData.push(i);
        item.isChecked = true;
        this.count();
      }
      if (this.selectedData.length < this.goods.length) {
        this.allchecked = false;
      } else {
        = to true this.allchecked;
       } 
      this.count (); 
      the console.log (this.selectedData);
    },
    // 商品数量
    the onChange (Item) 
      this.totallvd = totalLvd; { 
      Toast (item.num); 
      this.count (); 
      the console.log (this.goods);
     } , 
    // calculate price 
    COUNT: function () { 
      var the totalPrice = 0; // temporary total 
      var totalLvd = 0; // temporary LVD 
      this.goods.forEach (function (Val) { 
        IF (val.isChecked) { 
          the totalPrice + = val.num * val.price; // accumulated total 
          totalLvd + = val.num * val .lvd; // accumulated LVD
         } 
      }); 
      this.totalprice the totalPrice =; 
    }, 
    // Select 
    checkAll () { 
      the let List = this.goods; 
      IF (this.allchecked === to true) {
        list.forEach(element => {
          element.isChecked = false;
        });
        this.selectedData = [];
        this.count();
        console.log("111" + this.selectedData);
      } else {
        list.forEach(element => {
          element.isChecked = true;
          if (this.selectedData.indexOf(element.id) < 0) {
            this.selectedData.push(element.id);
          }
        });
        this.count();
        console.log("222" + this.selectedData);
      }
    },
    // 去结算
    onSubmit() {
      // 选择购买的商品
      var cartgoods = [];
      this.goods.forEach(function(item) {
        if (item.isChecked) {
          cartgoods.push({ id: item.id, num: item.num });
        }
      });
      if (cartgoods.length === 0) {
        Toast("请选择商品购买");
      } else {
        this.$router.push("shopBuy");
      }
      console.log(cartgoods);
    }
  }
};
</script>

<style lang="scss" scoped>
.shopCart {
  width: 100%;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  background-color: #f6f6f6;
  .cartList {
    width: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
    margin-top: 16px;
    ul {
      width: 100%;
      display: flex;
      flex-direction: column;
      align-items: center;
      margin-bottom: 100px;
      li {
        width: 100%;
        height: 96px;
        background-color: #fff;
        display: flex;
        flex-direction: row;
        align-items: center;
        margin-bottom: 12px;
        .van-checkbox {
          margin-left: 17px;
          ::v-deep .van-checkbox__icon {
            height: 14px;
            line-height: 14px;
            .van-icon {
              width: 14px;
              height: 14px;
              font-size: 12px;
              border: 1px solid #a5a5a5;
            }
          }
        }
        .shopdetail {
          display: flex;
          flex-direction: row;
          align-items: center;
          margin-left: 13px;
          .detailimg {
            width: 64px;
            height: 64px;
            background: rgba(165, 165, 165, 1);
            border-radius: 4px;
            img {
              width: 100%;
              height: 100%;
              border-radius: 4px;
            }
          }
          .detailtext {
            width: 230px;
            height: 60px;
            display: flex;
            flex-direction: column;
            margin-left: 8px;
            position: relative;
            .shoptitle {
              width: 180px;
              text-align: justify;
              font-size: 12px;
              color: #212121;
              line-height: 17px;
            }
            .shoppricenum {
              width: 100%;
              display: flex;
              flex-direction: row;
              align-items: center;
              justify-content: space-between;
              position: absolute;
              bottom: 0px;
              .shopprice {
                font-size: 12px;
                color: #15c481;
                font-weight: 600;
              }
              .shopnum {
                display: flex;
                ::v-deep .van-stepper {
                  button {
                    width: 14px;
                    height: 14px;
                    border: 1px solid #333333;
                    border-radius: 50px;
                    background-color: #fff;
                  }
                  .van-stepper__minus::before {
                    width: 8px;
                  }
                  .van-stepper__plus::before {
                    width: 8px;
                  }
                  .van-stepper__plus::after {
                    height: 8px;
                  }
                  .van-stepper__input {
                    font-size: 12px;
                    color: #333333;
                    background-color: #fff;
                    padding: 0px 12px;
                  }
                }
              }
            }
          }
        }
      }
    }
    .nohaveshop {
      display: flex;
      flex-direction: column;
      align-items: center;
      margin-top: 100px;
      .van-icon {
        font-size: 60px;
        color: #666;
      }
      p {
        font-size: 14px;
        color: #999;
      }
      .p1 {
        margin-top: 20px;
      }
    }
  }
  .cartfotter {
    width: 100%;
    height: 60px;
    position: fixed;
    bottom: 0;
    left: 0;
    .van-submit-bar__bar {
      height: 60px;
      font-size: 16px;
      .van-checkbox {
        margin-left: 17px;
        ::v-deep .van-checkbox__icon {
          height: 14px;
          line-height: 14px;
          .van-icon {
            width: 14px;
            height: 14px;
            font-size: 12px;
            border: 1px solid #a5a5a5;
          }
        }
        ::v-deep .van-checkbox__label {
          font-size: 16px;
          color: #212121;
          margin-left: 9px;
        }
      }
      .buyprice {
        flex: 1;
        padding-right: 8px;
        text-align: right;
        display: flex;
        flex-direction: column;
        .p1 {
          font-size: 10px;
          color: #001410;
        }
        .p2 {
          font-size: 12px;
          color: #15c481;
          margin-top: 4px;
        }
      }
      .van-button--danger {
        width: 130px;
        height: 60px;
        background: rgba(21, 196, 129, 1);
        border: none;
        font-size: 16px;
        color: #ffffff;
      }
    }
  }
}
</style>

The above code is useless to vuex, the purpose is to facilitate replication will be able to go directly to run the above code also applies to cases interface to get a shopping cart, local prices, vuex I introduce the following separate, on-demand added to it;

index.js in store

import Vue from "vue";
import Vuex from "vuex";
import app from "@/store/module/cart";
Vue.use(Vuex);

export default new Vuex.Store({
  state: {},
  mutations: {},
  actions: {},
  modules: {
    cart
  }
});

The code above we create a cart, dedicated to shopping cart module;

cart.js

export default {
  state: {
    // 购物车
    cartGoods: []
  },
  getters: {
    cartGoodIds(state) {
      return state.cartGoods.map(item => item.productId);
    }
  },
  mutations: {
    INIT_CART(state) {
      if (localStorage && localStorage.getItem("cartGoods")) {
        const goods = JSON.parse(localStorage.getItem("cartGoods"));
        state.cartGoods = goods;
      }
    },
    ADD_TO_CART(state, addGood) {
      const findGood = state.cartGoods.find(
        item => item.productId === addGood.productId
      );
      if (findGood) {
        findGood.num = findGood.num + addGood.num;
      } else {
        state.cartGoods.push(addGood);
      }
      if (localStorage) {
        localStorage.setItem("cartGoods", JSON.stringify(state.cartGoods));
      }
    },
    INPUT_TO_CART(state, inpGood) {
      const findGood = state.cartGoods.find(
        item => item.productId === inpGood.productId
      );
      const largeGood = state.cartGoods.find(item => item.num > inpGood.num);
      const equalGood = state.cartGoods.find(item => item.num == inpGood.num);
      const smallGood = state.cartGoods.find(item => item.num < inpGood.num);
      if (findGood && largeGood) {
        findGood.num = findGood.num - (findGood.num - inpGood.num);
      }
      if (findGood && equalGood) {
        findGood.num = inpGood.num;
      }
      if (findGood && smallGood) {
        findGood.num = inpGood.num;
      }
      if (localStorage) {
        localStorage.setItem("cartGoods", JSON.stringify(state.cartGoods));
      }
    }
  }
};

 

We have defined some of the above calculation methods and events, to change the information stored in the shopping cart page calls the other;

Other pages:

// 导入
import { mapGetters, mapMutations } from "vuex";
// 计算
computed: {
   ...mapGetters(["cartGoodIds"])
},
// 方法
methods: {
    ...mapMutations(["ADD_TO_CART", "INPUT_TO_CART", "INIT_CART"]),
}
// 使用
// 增加
// 增加
plusadd(item) {
  this.$store.commit("ADD_TO_CART", {
    productId: item.id,
    num: 1
  });
},
// 减少
minuscut(item) {
  this.$store.commit("ADD_TO_CART", {
    productId: item.id,
    num: -1
  });
},
// 输入
blurinput(item) {
  this.$store.commit("INPUT_TO_CART", {
    productId: item.id,
    num: parseInt(item.num)
  });
},

 

On the first rough introduction to here, we have raised any questions I promptly corrected, thank you!

Guess you like

Origin www.cnblogs.com/hejun26/p/12161591.html