最近使用Vue全家桶手撸了一个pc版小米商城的前端项目,对于组件通信和状态管理有了一个更加深刻的认识。因为组件划分的比较细,开始我使用的是基本的props和emit传值,后来发现一旦嵌套过深就变得很繁琐,同时考虑到有多个组件存在需要共同管理的状态,基本的传值已经没有办法满足需求了,所以使用到了vuex来划分模块管理状态。这里需要提一点就是,如果不存在多组件共同管理的状态,最好是不用vuex管理,vuex是用来管理多组件共同状态的,单单只需要实现跨组件、隔代组件通信的话,使用eventbus,provide/inject等就可以实现。
Vuex修改数据的一套基本流程
首先我们来弄清楚Vuex中管理数据的一套基本流程:
修改state中数据的流程:
在组件内派发一个action即dispatch(或者直接调用)一个action => action再commit一个mutation => mutation修改state
state中的数据都在action中请求,再通过commit一个mutation设置state中的数据
getter中存放着state的计算值,相当于组件中的计算属性(computed);同时getter中的值都是响应的,就是只要依赖的state一发生改变,getter中的值马上就能检测到,然后对应就会更新状态了
注意点:action中的请求是异步的,mutation是同步的
小米官网购物车功能分析
官方效果:
我们可以从上图中看到购物车的功能,这里我简单总结一下,分为以下十点:
全选功能按钮:当全选按钮亮时,代表下面所有单选按钮全部为选中状态;点击一下全选,再点击一下,全部取消;同时下面单选按钮全部选中时,上面全选按钮会自动更新状态为全选,此时再点击全选按钮就会全部取消;
单选按钮:点击一下选中当前这条商品,点击两下取消选中这条商品,当所有单选按钮选中时,上面全选按钮会自动亮(全选状态),只要当前购物车商品一条未选择,上面全选按钮就不会亮;
减少商品数量按钮:点击加号减少商品的数量;
增加商品数量按钮:点击加号增加商品的数量;
每条商品的总价:计算当前这一条商品的总价;
删除商品按钮:点击删除按钮,将这条商品删除购物车;
所有商品数量:显示当前购物车内所有商品的数量;
选中商品数量:显示当前购物车内选中了商品的数量;
所有选中商品的总价:计算当前购物车内所有选中的商品总价,不包括未选择的商品;
结算按钮:有选中商品时显示,未选择商品不显示;
功能已经分析完毕,接下来思考一下该怎么管理状态,以及划分模块
Vuex模块思路
因为是购物车,所以这里我将这个购物车里的状态在Vuex中划分为了两个模块;products模块和cart模块,products模块用来存放所有的商品数据列表信息,cart模块放置了购物车内商品的列表信息;这里需要提的一点是,因为cart模块中的每条商品信息是不需要提供类似prodcuts中一条商品的所有字段的,只需要提供几个关键的字段,然后到prodcuts模块中去查询该条商品的信息即可。可能描述不清,但在下面我会用代码展示,大家就会清楚了。
Vuex模块结构设计
我的store目录如下:
我简单介绍一下:
module文件夹放置着所有的模块,我这里暂时放置三个模块cart.js、products.js、user.js(可以不用看,和购物车的功能实现没有太大关系)
index.js文件整合所有模块的内容,每个模块中都存放各自模块的state、mutations、actions、getters
types.js存放着所有模块的mutations常量名,这里没有强制,就是Vuex也和Redux、Flux 中的状态管理一样,修改数据遵循一套流程。每次commit都是一个常量的函数。
types文件代码
// cart模块 export const CART_ADD_PRODUCT_TO_CART = 'CART_ADD_PRODUCT_TO_CART' // 添加购物车 export const CART_DEL_PRODUCT_TO_CART = 'CART_DEL_PRODUCT_TO_CART' // 删除购物车 export const CART_CHANGE_LOGIN_STATUS = 'CART_CHANGE_LOGIN_STATUS' // 切换登陆状态 export const CART_ADD_PRODUCT_QUANTITY = 'CART_ADD_PRODUCT_QUANTITY' // 添加商品数量 export const CART_DEL_PRODUCT_QUANTITY = 'CART_DEL_PRODUCT_QUANTITY' // 减少商品数量 export const CART_SET_CHECKOUT_STATUS_ALL = 'CART_SET_CHECKOUT_STATUS_ALL' // 一键改变所有商品购买状态的方法 // products模块 export const PRODUCTS_SET_PRODUCT = 'PRODUCTS_SET_PRODUCT' // 获取所有商品的列表