Vuex 解决了
多个视图依赖于同一状态
和来自不同视图的行为需要变更同一状态
的问题,将开发者的精力集中于数据的更新而不是数据在组件之间的传递上。本文以购物车为例,对概念没有过多阐述,建议先浏览官网:https://vuex.vuejs.org/
- 【页面】商品列表组件、购物车列表组件、商品结算组件
- 【功能】将商品加入购物车,更新购物车列表
- 【功能】增减商品时,库存、总数、总价变化
1.文件结构
store
├── index.js # 导出 store 的地方
├── state.js # 根级别的 state
├── getters.js # 二次包装state数据
├── actions.js # 根级别的 action
├── mutations.js # 根级别的 mutation
├── mutation-types.js # 所有 mutation 的常量映射表
2.安装
npm install vuex --save
3.在src目录下新建store/index.js
,代码如下:
import Vue from 'vue';
import Vuex from 'vuex';
import actions from '@/store/actions.js';
import getters from '@/store/getters.js';
import mutations from '@/store/mutations.js';
import state from '@/store/states.js';
Vue.use(Vuex);
export default new Vuex.Store({
state,
mutations,
getters,
actions,
})
4.在main.js文件中引入
import router from './router'
import store from './store/index'
new Vue({
el: '#app',
router,
util,
store,
components: {App},
template: ' '
})
5.页面搭建及组件实现(注:这里的组件都是全局注册的,可参考:https://blog.csdn.net/try_try_try/article/details/85264175)
- 数据准备
goodsData: [
{ 'id': 1, 'url':imgTmp, 'name': "美的洗碗机", 'price': 2000,'inventory':5,'num':1 },
{ 'id': 2, 'url':imgTmp, 'name': "美的豆浆机", 'price': 1000,'inventory':100,'num':1 },
{ 'id': 3, 'url':imgTmp, 'name': "美的微波炉", 'price': 1500,'inventory':80,'num':1 }
]
- 商品列表项组件(goodsItem)
{{good.name}}
库存: {{good.inventory}}
¥{{good.price|toFixed(2)}}
- 购物车列表组件(shopCartList )
-
{{good.name}}
库存: {{good.inventory}}
¥{{good.price|toFixed(2)}}
- 主页面,到目前为止我们就可以看到开篇的页面效果了
商品列表
-
购物车列表
空空如也~
6.下面终于到vuex登场啦,先来看看具体有哪些交互以及实现方式
- 由图我们可以看到购物车的列表数据是我们三个组件操作的数据源,那么我们来看看store/states.js 中的代码实现
//用于数据的存储,是store中的唯一数据源
const state = {
shopList:[]//购物车列表
};
export default state;
7.加入购物车功能
当点击加入购物车时,即需要修改store的state,我们知道更改 Vuex 的 store 中的状态的唯一方法是提交 mutation,由于mutation 必须同步执行,我们一般通过 action来提交mutation,下面我们来看看store/actions.js中的代码实现
//actions 类似于mutation,用于提交mutation来改变状态,而不直接变更状态,可以包含任意异步操作
import mutationTypes from './mutationTypes.js'
export default{
addGoods({commit},params){ //params对应mutation对象中参数info
commit(mutationTypes.ADD_GOODS,params);
}
}
store/mutationTypes.js
// 所有 mutation 的类型
const mutationTypes = {
ADD_GOODS: 'addGoods'
};
export default mutationTypes;
store/mutations.js
//mutations,改变state数据的唯一途径,且不能用于处理异步事件
import mutationTypes from './mutationTypes.js'
const mutations = {
[mutationTypes.ADD_GOODS](state, info) { //接受actions传过来的参数
let isOwn = state.shopList.some(function(item){
if(item.id == info.id){
if(item.inventory!=0){
item.num++;
item.inventory--;
}
return true;
}else{
return false;
}
});
if(!isOwn){
state.shopList.push({id:info.id,name:info.name,price:info.price,inventory:info.inventory-1,num:1});
}
}
};
export default mutations;
到此整个流程就很清晰了,actions从用户那里拿到数据后,提交给mutations,由mutation做数据的修改。
接下来就是在添加商品的组件中(goodsItem)引入mapActions并使用它:
现在我们就实现了将商品加入购物车的功能,增加数量(addNum)、减少数量(reduceNum)、移除商品(deleteGoods)、清空购物车(clearShopCart)与加入购物车实现方法一致。完整的actions、mutations如下:
import mutationTypes from './mutationTypes.js'
export default{
addGoods({commit},params){ //params对应mutation对象中参数info
commit(mutationTypes.ADD_GOODS,params);
},
addNum({commit},params){
console.log("addNum");
commit(mutationTypes.ADD_NUM,params);
},
reduceNum({commit},params){
commit(mutationTypes.REDUCE_NUM,params);
},
deleteGoods({commit},params){
commit(mutationTypes.DELETE_GOODS,params);
},
clearShopCart({commit}){
commit(mutationTypes.CLEAR_SHOP_CART);
}
}
import mutationTypes from './mutationTypes.js'
const mutations = {
[mutationTypes.ADD_GOODS](state, info) {
let isOwn = state.shopList.some(function(item){
if(item.id == info.id){
if(item.inventory!=0){
item.num++;
item.inventory--;
}
return true;
}else{
return false;
}
});
if(!isOwn){
state.shopList.push({id:info.id,name:info.name,price:info.price,inventory:info.inventory-1,num:1});
}
},
[mutationTypes.ADD_NUM](state, index) {
if(state.shopList[index].inventory!=0){
state.shopList[index].num++;
state.shopList[index].inventory--;
}
},
[mutationTypes.REDUCE_NUM](state, index) {
if(state.shopList[index].num == 0){
state.shopList.splice(index,1);
}else{
state.shopList[index].num--;
state.shopList[index].inventory++;
}
},
[mutationTypes.DELETE_GOODS](state, index) {
state.shopList.splice(index,1);
},
[mutationTypes.CLEAR_SHOP_CART](state) {
state.shopList = [];
},
}
;
export default mutations;
8.结算组件中(shopCartAccount)的数量以及金额统计,现在就到我们的store/getters.js登场了
//基于state数据的二次包装,常用于数据的筛选和多个数据的相关性计算
import state from './states.js';
export default{
totalPrice(){
let totalPrice = 0; // 计算总价
for(let i =0;i
结算组件中的使用:
至此,整个demo就完成了,vuex的简单使用也算是分享完了,感谢您看完了这篇长文,有哪里不明白的或不对的,留言下,咱们可以一起讨论、共同学习!