先来看一下标准的 vuex demo
- vuex 的状态管理:
state => getters => view => action => commit => mutations => state(new) => getters => view(new)
demo (from demo)
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const state = {
count: 0
}
const mutations = {
increment (state) {
state.count++
},
decrement (state) {
state.count--
}
}
const actions = {
increment: ({ commit }) => commit('increment'),
decrement: ({ commit }) => commit('decrement'),
incrementIfOdd ({ commit, state }) {
if ((state.count + 1) % 2 === 0) {
commit('increment')
}
},
incrementAsync ({ commit }) {
return new Promise((resolve, reject) => {
setTimeout(() => {
commit('increment')
resolve()
}, 1000)
})
}
}
const getters = {
evenOrOdd: state => state.count % 2 === 0 ? 'even' : 'odd'
}
export default new Vuex.Store({
state,
getters,
actions,
mutations
})
airforce 的封装设计
airforce.js
import { login } from '../api/login'
import initialState from './initialState'
import _ from 'lodash'
const AIRFORCE_DO = 'AIRFORCE_DO'
const AIRFORCE_LEAVE = 'AIRFORCE_LEAVE'
const apis = {
login
}
const state = initialState
const getters = {
airforce: state => state
}
// data = {
// moduleName: 'abc',
// apiName: 'login',
// apiConfig: {
// loginName: 'login',
// password: '123456'
// },
// goods: {
// loginFlag: true
// }
// }
const actions = {
action ({ commit }, data) {
if (data.loading) {
VUX.loading.show({
text: ''
})
}
if (data.apiName) {
if (typeof apis[data.apiName] !== 'function') {
return console.error('no matching apiName.')
}
apis[data.apiName](data.apiConfig).then(res => {
let result
try {
result = res.json()
} catch (e) {}
if (result) {
return result
}
return res
}).then(result => {
if (data.loading) {
VUX.loading.hide()
}
if (typeof result.data === 'object') {
data.goods = _.merge(data.goods, result.data)
} else {
data.goods.$resData = result.data
}
commit(AIRFORCE_DO, { data })
if (data.callback) {
data.callback(result.data)
}
if (result.status >= 200 && result.status < 300 && result.data.status !== 'ERROR') {
return Promise.resolve(result.data)
} else {
return Promise.reject(result)
}
}).then(res => {
if (data.success) {
data.success(res)
}
return res
}).catch(e => {
if (data.loading) {
VUX.loading.hide()
}
if (data.error) {
data.error(e)
}
if (!data.noError && e.data && e.data.message) {
VUX.toast.text(e.data.message)
}
return Promise.reject(e)
})
} else {
commit(AIRFORCE_DO, { data })
}
},
unload ({ commit }, data) {
commit(AIRFORCE_LEAVE, { data })
}
}
// mutations
const mutations = {
[AIRFORCE_DO] (state, { data }) {
if (typeof data.goods === 'object') {
state[data.moduleName] = _.merge(state[data.moduleName], data.goods)
} else {
state[data.moduleName] = data.goods
}
},
[AIRFORCE_LEAVE] (state, { data }) {
state[data.moduleName] = undefined
}
}
export default {
state,
getters,
actions,
mutations
}
initialState.js
export default {
abc: {
b: {
c: 'abc',
d: 3
}
}
}
initial state 结构确定了整个 state 响应式属性的内容
-
官网的对于响应式原理的解释:
image.png
login.js
import { fetch } from '../utils/fetch'
export function login ({username, password}) {
const data = {
username,
password
}
return fetch({
url: '/login',
method: 'post',
params: data
})
}
export function logout () {
return fetch({
url: '/logout',
method: 'post'
})
}
Promise.all 的设计
const a = this.action({
apiName: 'login'
})
const b = this.action({
apiName: 'getConfig'
})
Promise.all([a,b]).then(res=>{
console.log('init')
})
模块化设计
import Vue from 'vue'
import _ from 'lodash'
import axios from './axios'
import initState from './initState'
const AIRFORCE_DO = 'AIRFORCE_DO'
const AIRFORCE_LEAVE = 'AIRFORCE_LEAVE'
const AIRFORCE_SET = 'AIRFORCE_SET'
// initial state
const state = initState
// getters
const getters = {
airforce: state => {
const airforce = {
'$$global': {}
}
for (let i in state) {
if (state[i].__fromModule) {
_.set(airforce, `${[state[i].__fromModule]}.${i}`, state[i])
} else {
airforce.$$global[i] = state[i]
}
}
return {
...state,
...airforce
}
}
}
// actions
const actions = {
action ({ commit }, data) {
if (data.loading) {
// VUX.loading.show({
// text: ''
// })
}
const {goods, ...restData} = data
if (data.method && (data.url || data.fullUrl)) {
if (!data.goods) {
data.goods = {}
}
return axios(restData).then(res => {
let result
try {
result = res.json()
} catch (e) {}
if (result) {
return result
}
return res
}).then(result => {
if (data.loading) {
// VUX.loading.hide()
}
if (_.isObject(result.data) && !_.isArray(result.data)) {
data.goods = _.merge({}, data.goods, result.data)
} else {
_.set(data, 'goods.$resData', result.data)
}
commit(AIRFORCE_DO, data)
if (data.callback) {
data.callback(result.data)
}
if (result.status >= 200 && result.status < 300 && result.data.status !== 'ERROR') {
return Promise.resolve(result.data)
} else {
return Promise.reject(result)
}
}).then(res => {
if (data.success) {
data.success(res)
}
return res
}).catch(e => {
console.log(e)
if (data.loading) {
// VUX.loading.hide()
}
if (data.error) {
data.error(e)
}
if (!data.noError && e.data && e.data.message) {
// VUX.toast.text(e.data.message)
}
return Promise.reject(e)
})
}
commit(AIRFORCE_DO, data)
},
unload ({ commit }, data) {
commit(AIRFORCE_LEAVE, data)
},
stateSet ({ commit }, data) {
commit(AIRFORCE_SET, data)
}
}
// mutations
const mutations = {
[AIRFORCE_DO] (state, data) {
if (_.isObject(data.goods) && !_.isArray(data.goods)) {
Vue.set(state, data.moduleName, _.merge({__fromModule: '$$' + window.location.hash.replace(/^#\//, '')}, state[data.moduleName], data.goods))
} else {
Vue.set(state, data.moduleName, data.goods)
}
console.group()
console.log('action', data)
console.log('airforce', state)
console.groupEnd()
if (state.syncHeight) {
state.syncHeight()
}
},
[AIRFORCE_LEAVE] (state, data) {
state[data.moduleName] = undefined
if (state.syncHeight) {
state.syncHeight()
}
},
[AIRFORCE_SET] (state, data) {
data(state)
if (state.syncHeight) {
state.syncHeight()
}
}
}
export default {
state,
getters,
actions,
mutations
}
export function mapAirforce (arr) {
const result = {}
for (let i = 0; i < arr.length; i++) {
const item = arr[i]
Object.assign(result, {
[item] () {
return _.get(this.$store.getters.airforce, `$$${item}`)
}
})
}
return result
}
用法
import {mapAirforce} from '@/widgets'
...
computed: {
...mapAirforce(['merchantOrderList'])
},
...
// this.merchantOrderList就是改路由模块下的数据
网友评论