Vuex
2020-10-20 10:01:14 0 举报
AI智能生成
源码Vuex
作者其他创作
大纲/内容
Store
<b>constructor</b> (options = {})
this._modules = new ModuleCollection(options)
ModuleCollection
<b>constructor</b> (rawRootModule)
this.register([], rawRootModule, false)
<b>get</b> (path)
return path.reduce((module, key) => {<br> return module.getChild(key)<br> }, this.root)
<b>getNamespace</b> (path)
let module = this.root<br> return path.reduce((namespace, key) => {<br> module = module.getChild(key)<br> return namespace + (module.namespaced ? key + '/' : '')<br> }, '')
<b>update</b> (rawRootModule)
update (rawRootModule) {<br> update([], this.root, rawRootModule)<br> }
targetModule.update(newModule)
调用module.js中的update方法
if (newModule.modules),存在子模块,递归调用
<b>register</b> (path, rawModule, runtime = true)
const newModule = new Module(rawModule, runtime)
Module
<b>constructor</b> (rawModule, runtime)
get <b>namespaced</b> ()
return !!this._rawModule.namespaced
<b>addChild</b> (key, module)
this._children[key] = module
<b>removeChild</b> (key)
delete this._children[key]
<b>getChild</b> (key)
return this._children[key]
<b>update</b> (rawModule)
<b>forEachChild</b> (fn)
forEachChild (fn) {<br> forEachValue(this._children, fn)<br> }
<b>forEachGetter</b> (fn)
if (this._rawModule.getters) {<br> forEachValue(this._rawModule.getters, fn)<br> }
<b>forEachAction</b> (fn)
if (this._rawModule.actions) {<br> forEachValue(this._rawModule.actions, fn)<br> }
<b>forEachMutation</b> (fn)
if (this._rawModule.mutations) {<br> forEachValue(this._rawModule.mutations, fn)<br> }
if (path.length === 0) {<br> <b><font color="#f15a23">this.root</font></b> = newModule<br> } else {<br> const parent = this.get(path.slice(0, -1))<br> parent.addChild(path[path.length - 1], newModule)<br> }
register nested modules
if (rawModule.modules) {<br> forEachValue(rawModule.modules, (rawChildModule, key) => {<br> this.register(path.concat(key), rawChildModule, runtime)<br> })<br> }
<b>unregister</b> (path)
const parent = this.get(path.slice(0, -1))
const key = path[path.length - 1]
只可注销register的,不可注销构造函数创造的
if (!parent.getChild(key).runtime) return
parent.removeChild(key)
const { dispatch, commit } = this
this.dispatch = function boundDispatch (type, payload) {<br> return dispatch.call(store, type, payload)<br> }
this.commit = function boundCommit (type, payload, options) {<br> return commit.call(store, type, payload, options)<br> }
const state = this._modules.root.state
<b>installModule </b>(this, state, [], this._modules.root)
const namespace = store._modules.getNamespace(path)
if (module.namespaced)
store._modulesNamespaceMap[namespace] = module
set state
获取上下文
const local = module.context = <b>makeLocalContext</b>(store, namespace, path)
function <b>makeLocalContext</b> (store, namespace, path)
const noNamespace = namespace === ''
const <b>local</b> = {<br> dispatch,<br> commit<br>}<br>
dispatch
noNamespace ?
是
store.dispatch
否
(_type, _payload, _options) => {<br><span style="font-size: inherit;"> const args = unifyObjectStyle(_type, _payload, _options)</span><br><span style="font-size: inherit;"> const { payload, options } = args</span><br><span style="font-size: inherit;"> let { type } = args</span><br><br><span style="font-size: inherit;"> if (!options || !options.root) {</span><br><span style="font-size: inherit;"> type = namespace + type</span><br><span style="font-size: inherit;"> }</span><br><br><span style="font-size: inherit;"> return store.dispatch(type, payload)</span><br> }
commit
noNamespace ?
是
store.commit
否
(_type, _payload, _options) => {<br> const args = unifyObjectStyle(_type, _payload, _options)<br> const { payload, options } = args<br> let { type } = args<br><br> if (!options || !options.root) {<br> type = namespace + type<br> }<br><br> store.commit(type, payload, options)<br> }
Object.defineProperties local<br>
getters
getters: {<br> get: noNamespace<br> ? () => store.getters<br> : () => makeLocalGetters(store, namespace)<br> }
function <b>makeLocalGetters</b> (store, namespace)
判断缓存if (!store.<b>_makeLocalGettersCache</b>[namespace])
const <b>gettersProxy</b> = {}
const splitPos = namespace.length
Object.keys(<b>store.getters</b>).forEach(type => {})
const <b>localType</b> = type.slice(splitPos)
Object.defineProperty(gettersProxy, localType, {<br> get: () => store.getters[type],<br> enumerable: true<br> })
store._<b>makeLocalGettersCache</b>[namespace] = gettersProxy
<b>return</b> store._makeLocalGettersCache[namespace]
state
state: {<br> get: () => getNestedState(store.state, path)<br> }
function <b>getNestedState</b> (state, path)
return <b>path.reduce</b>((state, key) => state[key], <b>state</b>)
return local
注册mutations
module.forEachMutation((mutation, key) => {<br> const namespacedType = namespace + key<br> registerMutation(store, namespacedType, mutation, local)<br> })
function <b>registerMutation</b> (store, type, handler, local)
const entry = store.<b>_mutations</b>[type] || (store._mutations[type] = [])
entry.push
function <b>wrappedMutationHandler </b>(payload) {<br> handler.call(store, local.state, payload)<br>})
注册actions
module.forEachAction((action, key) => {<br> const type = action.root ? key : namespace + key<br> const handler = action.handler || action<br> registerAction(store, type, handler, local)<br> })
function <b>registerAction</b> (store, type, handler, local)
const entry = store.<b>_actions</b>[type] || (store._actions[type] = [])
entry.push
function <b>wrappedActionHandler</b> (payload)
let res = handler.call(store, {<br> dispatch: <b>local</b>.dispatch,<br> commit: <b>local</b>.commit,<br> getters: <b>local</b>.getters,<br> state: <b>local</b>.state,<br> rootGetters: store.getters,<br> rootState: store.state<br> }, payload)<br>
if (!isPromise(res)) {<br> res = Promise.resolve(res)<br> }
return res
注册getters
module.forEachGetter((getter, key) => {<br> const namespacedType = namespace + key<br> registerGetter(store, namespacedType, getter, local)<br> })
function <b>registerGetter </b>(store, type, rawGetter, local)
store.<b>_wrappedGetters</b>[type] = function wrappedGetter (store) {<br> return rawGetter(<br> <b>local</b>.state, // local state<br> <b>local</b>.getters, // local getters<br> store.state, // root state<br> store.getters // root getters<br> )<br> }
遍历子模块,递归安装
module.forEachChild((child, key) => {<br> <b>installModule</b>(store, rootState, path.concat(key), child, hot)<br> })
<b>resetStoreVM </b>(this, state)
function <b>resetStoreVM</b> (store, state, hot)
const oldVm = store._vm<br><br> // bind store public getters<br><b> store.getters</b> = {}<br> // reset local getters cache<br> store._makeLocalGettersCache = Object.create(null)<br> const <b>wrappedGetters</b> = store._wrappedGetters<br> const <b>computed</b> = {}
<b>forEachValue</b> wrappedGetters
<b>computed</b>[key] = partial(fn, store)
Object.defineProperty(<b>store.getters</b>, key, {<br> get: () => <b>store._vm[key]</b>,<br> enumerable: true // for local getters<br> })
<b>store._vm</b> = new Vue({<br> data: {<br> $$state: state<br> },<br> <b>computed</b><br> })
<b>enableStrictMode</b> (store)
if oldVm
if hot
store._withCommit(() => {<br> oldVm._data.$$state = null<br> })
Vue.nextTick(() => oldVm.$destroy())
plugins.forEach(plugin => plugin(this))
<b>get state</b> ()
return this._vm._data.$$state
<b>commit</b> (_type, _payload, _options)
unifyObjectStyle
const entry = this._mutations[type]
this._withCommit(() => {<br> entry.forEach(function commitIterator (handler) {<br> handler(payload)<br> })<br> })
this._subscribers<br> .slice() <br> .forEach(sub => sub(mutation, this.state))
<b>dispatch</b> (_type, _payload)
unifyObjectStyle
const entry = this._actions[type]
this._actionSubscribers中before函数的执行
const result = entry.length > 1<br> ? Promise.all(entry.map(handler => handler(payload)))<br> : entry[0](payload)
result.then中执行this._actionSubscribers中的after函数
<b>subscribe</b> (fn)
subscribe (fn) {<br> return genericSubscribe(fn, this._subscribers)<br> }
genericSubscribe
<b>subscribeAction</b> (fn)
subscribeAction (fn) {<br> const subs = typeof fn === 'function' ? { before: fn } : fn<br> return genericSubscribe(subs, this._actionSubscribers)<br> }
<b>watch</b> (getter, cb, options)
return this._watcherVM.$watch(() => getter(this.state, this.getters), cb, options)
<b>replaceState</b> (state)
replaceState (state) {<br> this._withCommit(() => {<br> this._vm._data.$$state = state<br> })<br> }
<b>registerModule </b>(path, rawModule, options = {})
if (typeof path === 'string') path = [path]
this._modules.register(path, rawModule)
installModule(this, this.state, path, this._modules.get(path), options.preserveState)
resetStoreVM(this, this.state)
<b>unregisterModule</b> (path)
if (typeof path === 'string') path = [path]
this._modules.unregister(path)
this._withCommit(() => {<br> const parentState = getNestedState(this.state, path.slice(0, -1))<br> Vue.delete(parentState, path[path.length - 1])<br> })
resetStore(this)
function <b>resetStore</b> (store, hot)
installModule(store, state, [], store._modules.root, true)
resetStoreVM(store, state, hot)
hotUpdate
hotUpdate (newOptions) {<br> this._modules.update(newOptions)<br> resetStore(this, true)<br> }
resetStore(this, true)
install
applyMixin(vue)
Vue.mixin({ beforeCreate: vuexInit })
options.store
this.$store = options.store
options.parent && options.parent.$store
this.$store = options.parent.$store
mapState
normalizeNamespace
normalizeMap
res[key] = function mappedState
return typeof val === 'function'<br> ? val.call(this, state, getters)<br> : state[val]
mapMutations
normalizeNamespace
normalizeMap
res[key] = function mappedMutation (...args)
return typeof val === 'function'<br> ? val.apply(this, [commit].concat(args))<br> : commit.apply(this.$store, [val].concat(args))
mapGetters
normalizeNamespace
normalizeMap
res[key] = function mappedGetter
val = namespace + val
return this.$store.getters[val]
mapActions
normalizeNamespace
normalizeMap
res[key] = function mappedAction (...args)
return typeof val === 'function'<br> ? val.apply(this, [dispatch].concat(args))<br> : dispatch.apply(this.$store, [val].concat(args))
createNameSpacedHelpers
export const createNamespacedHelpers = (namespace) => ({<br> mapState: mapState.bind(null, namespace),<br> mapGetters: mapGetters.bind(null, namespace),<br> mapMutations: mapMutations.bind(null, namespace),<br> mapActions: mapActions.bind(null, namespace)<br>})
0 条评论
下一页