基于Vuex实现小米商城购物车(上)

实现步骤
1. 静态页面准备

页面使用了 element-ui 的Icon 图标、el-checkbox、el-input-number、el-popover、el-button,所有在main.js需要引入element-ui。

import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);

页面代码如下:
说明: 为了方便,此处直接放最终的代码。

2. 创建Vuex
/store/index.js

import Vue from 'vue'
import Vuex from 'vuex'
 
import shoppingCart from './modules/shoppingCart'
 
Vue.use(Vuex)
 
export default new Vuex.Store({
  strict: true,
  modules: {
    shoppingCart
  }
})
复制代码/store/modules/shoppingCart.js
export default {
  state: {
    shoppingCart: []
    // shoppingCart结构
    /*
    shoppingCart = {
      id: "", // 购物车id
      productID: "", // 商品id
      productName: "", // 商品名称
      productImg: "", // 商品图片
      price: "", // 商品价格
      num: "", // 商品数量
      maxNum: "", // 商品限购数量
      check: false // 是否勾选
    }
    */
  }
}

复制代码3. 同步购物车状态
思路:

在根组件App.vue监听用户登录状态;
如果用户已经登录,从数据库获取用户的购物车数据,把获取到数据更新到vuex;
用户没有登录,把vuex中购物车的状态设置为空。

代码如下:

import { mapActions } from "vuex";
import { mapGetters } from "vuex";
 
computed: {
  ...mapGetters(["getUser", "getNum"])
},
methods: {
  ...mapActions(["setShoppingCart"]),
}
watch: {
  // 获取vuex的登录状态
  getUser: function(val) {
    if (val === "") {
      // 用户没有登录
      this.setShoppingCart([]);
    } else {
      // 用户已经登录,获取该用户的购物车信息
      this.$axios
        .post("/api/user/shoppingCart/getShoppingCart", {
          user_id: val.user_id
        })
        .then(res => {
          if (res.data.code === "001") {
            // 001 为成功, 更新vuex购物车状态
            this.setShoppingCart(res.data.shoppingCartData);
          } else {
            // 提示失败信息
            this.notifyError(res.data.msg);
          }
        })
        .catch(err => {
          return Promise.reject(err);
        });
    }
  }
}
vuex的mutations:
setShoppingCart (state, data) {
        // 设置购物车状态
        state.shoppingCart = data;
},
vuex的actions
setShoppingCart({ commit }, data) {
  commit('setShoppingCart', data);
}

4. 动态生成购物车页面
思路:

通过vuex中的getters.getShoppingCart获取购物车的状态;
使用v-if判断购物车是否存在商品;
如果存在,使用v-for生成购物车列表;
如果不存在,显示购物车为空的时候显示的内容;

购物车html伪代码:

您的购物车还是空的!

快去购物吧!

vuex的getters: getShoppingCart(state) { // 获取购物车状态 return state.shoppingCart; }

5.添加商品到购物车
思路:

用户在商品的详情页,通过点击加入购物车按钮,调用点击事件addShoppingCart;
先向后端发起添加购物车的请求,根据返回信息操作vuex;
该商品第一次加入购物车:通过vuex的 Actions (unshiftShoppingCart)把后端返回的购物车信息插入vuex;
该商品已经在购物车,通过vuex的 Actions (addShoppingCartNum)把该商品数量+1;
商品数量达到限购数量,禁止点击加入购物车按钮。

html:


  加入购物车

复制代码逻辑代码如下:
methods: {
  ...mapActions(["unshiftShoppingCart", "addShoppingCartNum"]),
  // 加入购物车
  addShoppingCart() {
    // 判断是否登录,没有登录则显示登录组件
    if (!this.$store.getters.getUser) {
      this.$store.dispatch("setShowLogin", true);
      return;
    }
    // 向后端发起请求,把商品信息插入数据库的购物车表
    this.$axios
      .post("/api/user/shoppingCart/addShoppingCart", {
        user_id: this.$store.getters.getUser.user_id,
        product_id: this.productID
      })
      .then(res => {
        switch (res.data.code) {
          case "001":
            // 新加入购物车成功
            this.unshiftShoppingCart(res.data.shoppingCartData[0]);
            this.notifySucceed(res.data.msg);
            break;
          case "002":
            // 该商品已经在购物车,数量+1
            this.addShoppingCartNum(this.productID);
            this.notifySucceed(res.data.msg);
            break;
          case "003":
            // 商品数量达到限购数量
            this.dis = true;
            this.notifyError(res.data.msg);
            break;
          case "401":
            // 没有登录
            this.$store.dispatch("setShowLogin", true);
            this.notifyError(res.data.msg);
            break;
          default:
            this.notifyError(res.data.msg);
        }
      })
      .catch(err => {
        return Promise.reject(err);
      });
  }
}
复制代码vuex的mutations:
unshiftShoppingCart(state, data) {
  // 添加商品到购物车
  // 用于在商品详情页点击添加购物车,后台添加成功后,更新vuex状态
  state.shoppingCart.unshift(data);
},
addShoppingCartNum(state, productID) {
  // 增加购物车商品数量
  // 用于在商品详情页点击添加购物车,后台返回002,“该商品已在购物车,数量 +1”,更新vuex的商品数量
  for (let i = 0; i < state.shoppingCart.length; i++) {
    const temp = state.shoppingCart[i];
    if (temp.productID == productID) {
      if (temp.num < temp.maxNum) {
        temp.num++;
      }
    }
  }
}
复制代码vuex的actions:
unshiftShoppingCart({ commit }, data) {
  commit('unshiftShoppingCart', data);
},
addShoppingCartNum({ commit }, productID) {
  commit('addShoppingCartNum', productID);
}

6. 删除购物车中的商品
思路:

购物车每个商品都有一个删除按钮,用户点击删除按钮,先弹出确认对话框;
当用户选择确认删除,调用点击事件deleteItem($event,item.id,item.productID);
通过点击事件获取到购物车id和商品id;
先向后端发起删除购物车的请求,根据返回信息操作vuex;
删除成功,通过通过vuex的 Actions (deleteShoppingCart),把该商品从购物车删除;
如果删除失败,提示相关信息。

确定删除吗?

确定

逻辑代码如下:

methods: {
  // 向后端发起删除购物车的数据库信息请求
  deleteItem(e, id, productID) {
    this.$axios
      .post("/api/user/shoppingCart/deleteShoppingCart", {
        user_id: this.$store.getters.getUser.user_id,
        product_id: productID
      })
      .then(res => {
        switch (res.data.code) {
          case "001":
            // 删除成功
            // 更新vuex状态
            this.deleteShoppingCart(id);
            // 提示删除成功信息
            this.notifySucceed(res.data.msg);
            break;
          default:
            // 提示删除失败信息
            this.notifyError(res.data.msg);
        }
      })
      .catch(err => {
        return Promise.reject(err);
      });
  }
}

vuex的mutations:

deleteShoppingCart(state, id) {
  // 根据购物车id删除购物车商品
  for (let i = 0; i < state.shoppingCart.length; i++) {
    const temp = state.shoppingCart[i];
    if (temp.id == id) {
      state.shoppingCart.splice(i, 1);
    }
  }
}

vuex的actions:

deleteShoppingCart({ commit }, id) {
  commit('deleteShoppingCart', id);
}

7. 修改购物车商品的数量
思路:

购物车每个商品都有一个计数器,可以点击加减按钮修改商品数量,或者直接在input输入框输入商品数量进行修改。计数器使用了 element-ui 的el-input-number实现。
通过计数器的 change 事件获取到新的数量、购物车商品的索引(即数组的索引)、商品id;
先向后端发起修改购物车商品数量的请求,根据返回信息操作vuex;
修改成功,通过vuex的 Actions (updateShoppingCart),修改购物车商品的数量;
修改失败,提示失败信息。其中:数量小于1、数量是否达到限购数量(这两种情况,前端有设置校验,一般不会出现)。

html:

逻辑代码如下:

// 修改商品数量的时候调用该函数
handleChange(currentValue, key, productID) {
  // 当修改数量时,默认勾选
  this.updateShoppingCart({ key: key, prop: "check", val: true });
  // 向后端发起修改购物车商品数量的请求
  this.$axios
    .post("/api/user/shoppingCart/updateShoppingCart", {
      user_id: this.$store.getters.getUser.user_id,
      product_id: productID,
      num: currentValue
    })
    .then(res => {
      switch (res.data.code) {
        case "001":
          // 001代表修改成功
          // 更新vuex状态
          this.updateShoppingCart({
            key: key,
            prop: "num",
            val: currentValue
          });
          // 提示修改成功信息
          this.notifySucceed(res.data.msg);
          break;
        default:
          // 提示修改失败信息
          this.notifyError(res.data.msg);
      }
    })
    .catch(err => {
      return Promise.reject(err);
    });
}

 

你可能感兴趣的:(技术交流,传智播客西安中心)