点击“加入购物车”后,商品信息便被保存在product对象中了,而要想把product对象分享给购物车Cart组件,最好的办法就是将它加入到全局的vuex中。

我们创建一个store文件夹,将index.js文件作为状态管理模块的入口,代码如下:

import Vue from 'vue'
import Vuex from 'vuex'

import mutations from './mutations'
import actions from './actions'
import getters from './getters';

Vue.use(Vuex)

const state = {
  cartList: []
}

const store = new Vuex.Store({
  state,
  mutations,
  actions,
  getters
})

export default store

注意到mutations、actions和getters都被抽离出去了,state虽然没有抽离,但也单独进行了定义。而且在实例化store对象时,不是直接调用Vuex构造函数,而是调用其Vuex.Store方法。

在Detail组件中的addToCart方法中,最后一行为:

this.$store.dispatch('addCart',product)

这条语句的功能为,将product作为参数,调用actions中的addCart方法。而addCart方法定义如下:

addCart(context, payload){
    let oldProduct = context.state.cartList.find( item => item.iid === payload.iid)
    if (oldProduct) {
      //  如果是已有商品,则数量加一
      context.commit(ADD_COUNTER, oldProduct)
    }else{
      //  如果是新商品,则添加一个新item,且其数量初始化为1
      payload.count = 1
      context.commit(ADD_TO_CART, payload)
    }  
  }

基本逻辑是:首先判断当前购物车列表中有没有新加入的这件商品,如果有,则数量加一;如果没有,则作为新商品加入,数量初始化为1。

那为什么这个功能不直接在mutations中实现呢?原因是我们希望mutations中的方法功能都比较单一,而addCart中存在一个判断逻辑,两种判断结果对应两种截然不同的操作,所以我们需要将其放在actions中。此外,由于state中的数据只能在mutations中修改,所以具体的操作还是需要在mutaions中来完成——context.commit的功能就是将oldProduct或payload作为参数,调用mutaions中的ADD_COUNT方法或ADD_TO_CART方法。(这里的形参名context、payload都是约定俗成的。)

  [ADD_COUNTER](state, payload){
    payload.count++
  },
  [ADD_TO_CART](state, payload){
    state.cartList.push(payload)
  }

事实上,mutations中的方法名通常为定义好的常量,所以在store文件夹中还要有一个专门定义常量的文件mutations-types.js。

export const ADD_COUNTER = 'add_counter'
export const ADD_TO_CART = 'add_to_cart'

 

posted on 2021-07-01 14:59  springxxxx  阅读(204)  评论(0编辑  收藏  举报