应用场景
项目中存在多个页面使用同一数据或者共享某个组件,当某一处数据发生改变,期望其他地方响应式地发生改变,如果使用路由传值或本地存储导致项目难度加大,不妨试试vuex。
需求分析
如何引入vuex?
在vue-cli中如何使用?
开发流程
引入vuex
1.1 npm install vuex -S
1.2 在src文件夹下创建store文件夹,用于存放与vuex相关的js文件,这里主要介绍两种方式:
一、简单项目的store结构
只需在store文件夹下放一个单独的文件index.js即可,如下所示:
import Vue from 'vue'import Vuex from 'vuex'import {
getUserInfo,
getNotReadMessageNum
} from '../service/getData'import {setStore, getStore} from '../config/mUtils'Vue.use(Vuex)
export default new Vuex.Store({
state: {
userInfo: {},// 用户信息
msg_not_read_num: 0, // 未读消息数
session_id: '', // PHPSESSID
},
actions: {
async getUserInfo ({
commit,
state
}) { let res = await getUserInfo(); let info = res.data;
commit('GET_USERINFO', info);
},
async getMsgNotReadNum ({
commit,
state
}) { let res = await getNotReadMessageNum(); let num = res.data.message_num;
commit('GET_MSG_NOT_READ_NUM', num);
}
},
mutations: { // 获取用户信息
GET_USERINFO (state, info) {
state.userInfo = info;
}, // 获取消息未读数
GET_MSG_NOT_READ_NUM (state, num) {
state.msg_not_read_num = num;
}, // 记录PHPSESSID
RECORD_SESSION_ID (state, session_id) {
state.session_id = session_id;
setStore('session_id', state.session_id);
}
},
getters: {
}
})二、复杂项目的store结构
将vuex模块化,封装多个js文件,好处:条理清晰,结构明了
—store
—-index.js
—-actions.js
—-mutation-types.js
—-mutations.js
—-getters.js
index.js
import Vue from 'vue'import Vuex from 'vuex'import mutations from './mutations'import actions from './action'import getters from './getters'import {getStore} from '../mConfig/mUtils'Vue.use(Vuex)const state = {
userInfo: {
username: ''
}, //用户信息
shopInfo: null, // 我的小店信息
choosedAddress: getStore('choosedAddress') != undefined ? JSON.parse(getStore('choosedAddress')) : null, // 当前选择的地址
choosedClientAddress: getStore('choosedClientAddress') != undefined ? JSON.parse(getStore('choosedClientAddress')) : [], // 代客下单选择的地址
choosedCartList: getStore('choosedCartList') != undefined ? JSON.parse(getStore('choosedCartList')) : null, // 当前购物车选择结算的 item 列表
itemType: [], // 商品分类
couponIds: getStore('couponIds') != undefined ? JSON.parse(getStore('couponIds')) : [], // 已选择的优惠券id}
export default new Vuex.Store({
state,
getters,
actions,
mutations,
})actions.js
import {
getShopinfo,
getShopSortList
} from '../service/myApi';
import {
GET_SHOPINFO,
INIT_ITEM_TYPE
} from './mutation-types';
import Vue from 'vue';const vm = new Vue();
export default {
async getShopInfo({
commit,
state
}) { let res = await getShopinfo(); if (res.code === 0) {
commit(GET_SHOPINFO, res.data);
} else {
vm.$toast(res.error_msg);
}
},
async getItemType({
commit,
state
}) { let res = await getShopSortList(); if (res.code === 0) { let {
list
} = res.data;
commit(INIT_ITEM_TYPE, list);
} else {
vm.$toast(res.error_msg);
}
}
}mutation-types.js
export const CHOOSE_ADDRESS = 'CHOOSE_ADDRESS'; // 采购进货选择地址export const CHANGE_CART_LIST = 'CHANGE_CART_LIST'; // 购物车选择 itemexport const GET_SHOPINFO = 'GET_SHOPINFO'; // 获取我的小店信息export const INIT_ITEM_TYPE = 'INIT_ITEM_TYPE'; // 初始化商品分类export const ADD_ITEM_TYPE = 'ADD_ITEM_TYPE'; // 添加商品分类export const RESET_ITEM_TYPE = 'RESET_ITEM_TYPE'; // 重置商品分类export const CHANGE_CLIENT_ADDRESS = 'CHANGE_CLIENT_ADDRESS'; // 改变代客下单选择的地址export const EDIT_CLIENT_ADDRESS = 'EDIT_CLIENT_ADDRESS'; // 编辑某个代客下单选择的地址export const UPDATE_COUPON_IDS = 'UPDATE_COUPON_IDS'; // 修改couponIdsexport const CLEAR_CLIENT_ADDRESS = 'CLEAR_CLIENT_ADDRESS'; // 清空代客下单选择的地址mutations.js
import * as types from './mutation-types'import { setStore } from "../mConfig/mUtils";
import Vue from 'vue';
import VueRouter from 'vue-router';const vm = new Vue();const router = new VueRouter();const typeIsExist = (types, type) => { for(let i = 0; i < types.length; i++) { if (types[i].title === type) { return true;
}
} return false;
}
export default {
[types.CHOOSE_ADDRESS] (state, address) {
console.log(address);
state.choosedAddress = address;
setStore('choosedAddress', state.choosedAddress);
},
[types.CHANGE_CART_LIST] (state, cart_list) {
state.choosedCartList = cart_list;
setStore('choosedCartList', state.choosedCartList);
},
[types.GET_SHOPINFO] (state, info) {
state.shopInfo = {...info};
},
[types.ADD_ITEM_TYPE] (state, type) { if (!typeIsExist(state.itemType, type)) {
state.itemType.push({
title: type,
checked: false
});
vm.$toast('添加成功');
setTimeout(() => {
router.back();
}, 500);
} else {
vm.$toast('该分类已经存在');
}
},
[types.RESET_ITEM_TYPE] (state, types) {
state.itemType = [...types];
},
[types.INIT_ITEM_TYPE] (state, types) { let tmpList = [...types]; for(let i = 0; i < tmpList.length; i++) {
tmpList[i] = {
...tmpList[i],
checked: false
};
}
state.itemType = [...tmpList];
},
[types.CHANGE_CLIENT_ADDRESS] (state, address) {
state.choosedClientAddress.push(address);
setStore('choosedClientAddress', state.choosedClientAddress);
},
[types.EDIT_CLIENT_ADDRESS] (state, {index, address}) {
console.log(index, address);
state.choosedClientAddress.splice(index, 1, address);
setStore('choosedClientAddress', state.choosedClientAddress);
},
[types.UPDATE_COUPON_IDS] (state, coupon_id) { if (state.couponIds.indexOf(coupon_id) < 0) {
state.couponIds.push(coupon_id);
}
setStore('couponIds', state.couponIds);
},
[types.CLEAR_CLIENT_ADDRESS] (state) {
state.choosedClientAddress = [];
setStore('choosedClientAddress', state.choosedClientAddress);
}
}gettes.js
export default {
}1.3 main.js中引入
import store from './store'new Vue({
router,
store,
}).$mount('#app')项目使用
import { mapState, mapMutations } from 'vuex';
computed: {
...mapState([ 'choosedCartList'
])
},
methods: {
...mapMutations([ 'CHOOSE_ADDRESS', 'CHANGE_CART_LIST', 'CHANGE_CLIENT_ADDRESS', 'EDIT_CLIENT_ADDRESS'
]), // 选择地址
async chooseAddress(index) { this.activeIndex = index; // 代客下单
if (this.from_page === '/confirm_valet_order' || this.from_page === '/addClient') { let choosedIndex = this.$route.query.choosedIndex; if (window.localStorage.getItem('is_single') != undefined && window.localStorage.getItem('is_single')) { if (choosedIndex >= 0) {
console.log(this.address_list[index]); this.EDIT_CLIENT_ADDRESS({index: choosedIndex, address: this.address_list[index]});
} else { this.CHANGE_CLIENT_ADDRESS(this.address_list[index]);
}
} else { this.EDIT_CLIENT_ADDRESS({index: 0, address: this.address_list[index]});
}
} else if (this.from_page === '/confirm_purchase_order' || this.from_page === '/wxControlAddress') { // 采购进货
this.CHOOSE_ADDRESS(this.address_list[index]);
}
setTimeout(() => { this.$router.back();
}, 500);
}
}总结
本文主要介绍了vue-cli如何引入vuex并在项目中使用,包括项目结构及模块化的结构划分;
请务必遵守以下规则:
1) 应用层级的状态应该集中到单个 store 对象中。
2) 提交 mutation 是更改状态的唯一方法,并且这个过程是同步的。
3) 异步逻辑都应该封装到 action 里面。