使用的源碼版本為3.5.1
定義
Vuex 是一個(gè)專為 Vue.js 應(yīng)用程序開發(fā)的狀態(tài)管理模式蹂楣。它采用集中式存儲(chǔ)管理應(yīng)用的所有組件的狀態(tài)澳化,并以相應(yīng)的規(guī)則保證狀態(tài)以一種可預(yù)測(cè)的方式發(fā)生變化。
使用場(chǎng)景
它的優(yōu)勢(shì)用于解決下面兩個(gè)問題:
- 多個(gè)視圖依賴于同一狀態(tài)澈蚌。
- 來自不同視圖的行為需要變更同一狀態(tài)莉钙。
解決方式是:
- 全局單例集中管理
- 數(shù)據(jù)單向流動(dòng)
源碼架構(gòu)
vuex源碼架構(gòu)核心點(diǎn)兩個(gè):
- 觀察者模式
- 把state中的狀態(tài)處理成響應(yīng)式的
觀察者模式
我們定義的Action和Mutation都是具體的事件仇冯,會(huì)被vuex搜集保存起來
function installModule (store, rootState, path, module, hot) {
module.forEachMutation((mutation, key) => {
const namespacedType = namespace + key
registerMutation(store, namespacedType, mutation, local)
})
module.forEachAction((action, key) => {
const type = action.root ? key : namespace + key
const handler = action.handler || action
registerAction(store, type, handler, local)
})
}
function registerMutation (store, type, handler, local) {
const entry = store._mutations[type] || (store._mutations[type] = [])
entry.push(function wrappedMutationHandler (payload) {
handler.call(store, local.state, payload)
})
}
function registerAction (store, type, handler, local) {
const entry = store._actions[type] || (store._actions[type] = [])
entry.push(function wrappedActionHandler (payload) {
let res = handler.call(store, {
dispatch: local.dispatch,
commit: local.commit,
getters: local.getters,
state: local.state,
rootGetters: store.getters,
rootState: store.state
}, payload)
if (!isPromise(res)) {
res = Promise.resolve(res)
}
if (store._devtoolHook) {
return res.catch(err => {
store._devtoolHook.emit('vuex:error', err)
throw err
})
} else {
return res
}
})
}
dispatch和commit的作用是發(fā)布事件
// 只保留核心代碼
dispatch (_type, _payload) {
// check object-style dispatch
const {
type,
payload
} = unifyObjectStyle(_type, _payload)
const action = { type, payload }
const entry = this._actions[type]
const result = entry.length > 1
? Promise.all(entry.map(handler => handler(payload)))
: entry[0](payload)
// 只保留核心代碼
commit (_type, _payload, _options) {
// check object-style commit
const {
type,
payload,
options
} = unifyObjectStyle(_type, _payload, _options)
const mutation = { type, payload }
const entry = this._mutations[type]
this._withCommit(() => {
entry.forEach(function commitIterator (handler) {
handler(payload)
})
})
}
dispach發(fā)布事件,遍歷找到對(duì)應(yīng)的action處理已烤,處理異步操作完成之后調(diào)用commit提交事件鸠窗,遍歷找到對(duì)應(yīng)的mutation去處理(主要是修改state中數(shù)據(jù)狀態(tài)),這樣就完成了整個(gè)流程
響應(yīng)式原理
在store的構(gòu)造器中會(huì)調(diào)用resetStoreVM
// 只保留核心代碼
function resetStoreVM (store, state, hot) {
store._vm = new Vue({
data: {
$$state: state
},
computed
})
}
核心是創(chuàng)建一個(gè)vue實(shí)例胯究,利用vue響應(yīng)式原理把state的中的數(shù)據(jù)處理成響應(yīng)式的稍计。
vue響應(yīng)式的原理可以看我的這篇文章:從源碼的角度分析Vue視圖更新和nexttick機(jī)制
參考:
http://www.reibang.com/p/d95a7b8afa06
https://vuex.vuejs.org/zh/guide/actions.html
https://tech.meituan.com/2017/04/27/vuex-code-analysis.html