|
@@ -11,7 +11,6 @@ class Store {
|
|
|
|
|
|
const {
|
|
|
state = {},
|
|
|
- modules = {},
|
|
|
plugins = [],
|
|
|
strict = false
|
|
|
} = options
|
|
@@ -21,6 +20,7 @@ class Store {
|
|
|
this._committing = false
|
|
|
this._actions = Object.create(null)
|
|
|
this._mutations = Object.create(null)
|
|
|
+ this._wrappedGetters = Object.create(null)
|
|
|
this._subscribers = []
|
|
|
this._pendingActions = []
|
|
|
|
|
@@ -34,16 +34,17 @@ class Store {
|
|
|
return commit.call(store, type, payload)
|
|
|
}
|
|
|
|
|
|
- // init state and getters
|
|
|
- const getters = extractModuleGetters(options.getters, modules)
|
|
|
- initStoreState(this, state, getters)
|
|
|
+ // strict mode
|
|
|
+ this.strict = strict
|
|
|
+
|
|
|
+ // init internal vm with root state
|
|
|
+ // other options and sub modules will be
|
|
|
+ // initialized in this.module method
|
|
|
+ initStoreVM(this, state, {})
|
|
|
|
|
|
// apply root module
|
|
|
this.module([], options)
|
|
|
|
|
|
- // strict mode
|
|
|
- if (strict) enableStrictMode(this)
|
|
|
-
|
|
|
// apply plugins
|
|
|
plugins.concat(devtoolPlugin).forEach(plugin => plugin(this))
|
|
|
}
|
|
@@ -67,39 +68,10 @@ class Store {
|
|
|
if (typeof path === 'string') path = [path]
|
|
|
assert(Array.isArray(path), `module path must be a string or an Array.`)
|
|
|
|
|
|
- const isRoot = !path.length
|
|
|
- const {
|
|
|
- state,
|
|
|
- actions,
|
|
|
- mutations,
|
|
|
- modules
|
|
|
- } = module
|
|
|
-
|
|
|
- // set state
|
|
|
- if (!isRoot && !hot) {
|
|
|
- const parentState = getNestedState(this.state, path.slice(0, -1))
|
|
|
- if (!parentState) debugger
|
|
|
- const moduleName = path[path.length - 1]
|
|
|
- Vue.set(parentState, moduleName, state || {})
|
|
|
- }
|
|
|
-
|
|
|
- if (mutations) {
|
|
|
- Object.keys(mutations).forEach(key => {
|
|
|
- this.mutation(key, mutations[key], path)
|
|
|
- })
|
|
|
- }
|
|
|
+ initModule(this, path, module, hot)
|
|
|
|
|
|
- if (actions) {
|
|
|
- Object.keys(actions).forEach(key => {
|
|
|
- this.action(key, actions[key], path)
|
|
|
- })
|
|
|
- }
|
|
|
+ initStoreVM(this, this.state, this._wrappedGetters)
|
|
|
|
|
|
- if (modules) {
|
|
|
- Object.keys(modules).forEach(key => {
|
|
|
- this.module(path.concat(key), modules[key], hot)
|
|
|
- })
|
|
|
- }
|
|
|
this._committing = false
|
|
|
}
|
|
|
|
|
@@ -203,6 +175,7 @@ class Store {
|
|
|
hotUpdate (newOptions) {
|
|
|
this._actions = Object.create(null)
|
|
|
this._mutations = Object.create(null)
|
|
|
+ this._wrappedGetters = Object.create(null)
|
|
|
const options = this._options
|
|
|
if (newOptions.actions) {
|
|
|
options.actions = newOptions.actions
|
|
@@ -210,28 +183,15 @@ class Store {
|
|
|
if (newOptions.mutations) {
|
|
|
options.mutations = newOptions.mutations
|
|
|
}
|
|
|
+ if (newOptions.getters) {
|
|
|
+ options.getters = newOptions.getters
|
|
|
+ }
|
|
|
if (newOptions.modules) {
|
|
|
for (const key in newOptions.modules) {
|
|
|
options.modules[key] = newOptions.modules[key]
|
|
|
}
|
|
|
}
|
|
|
this.module([], options, true)
|
|
|
-
|
|
|
- // update getters
|
|
|
- const getters = extractModuleGetters(newOptions.getters, newOptions.modules)
|
|
|
- if (Object.keys(getters).length) {
|
|
|
- const oldVm = this._vm
|
|
|
- initStoreState(this, this.state, getters)
|
|
|
- if (this.strict) {
|
|
|
- enableStrictMode(this)
|
|
|
- }
|
|
|
- // dispatch changes in all subscribed watchers
|
|
|
- // to force getter re-evaluation.
|
|
|
- this._committing = true
|
|
|
- oldVm.state = null
|
|
|
- this._committing = false
|
|
|
- Vue.nextTick(() => oldVm.$destroy())
|
|
|
- }
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -239,7 +199,9 @@ function assert (condition, msg) {
|
|
|
if (!condition) throw new Error(`[vuex] ${msg}`)
|
|
|
}
|
|
|
|
|
|
-function initStoreState (store, state, getters) {
|
|
|
+function initStoreVM (store, state, getters) {
|
|
|
+ const oldVm = store._vm
|
|
|
+
|
|
|
// bind getters
|
|
|
store.getters = {}
|
|
|
const computed = {}
|
|
@@ -262,30 +224,67 @@ function initStoreState (store, state, getters) {
|
|
|
computed
|
|
|
})
|
|
|
Vue.config.silent = silent
|
|
|
+
|
|
|
+ // enable strict mode for new vm
|
|
|
+ if (store.strict) {
|
|
|
+ enableStrictMode(store)
|
|
|
+ }
|
|
|
+
|
|
|
+ if (oldVm) {
|
|
|
+ // dispatch changes in all subscribed watchers
|
|
|
+ // to force getter re-evaluation.
|
|
|
+ store._committing = true
|
|
|
+ oldVm.state = null
|
|
|
+ store._committing = false
|
|
|
+ Vue.nextTick(() => oldVm.$destroy())
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-function extractModuleGetters (getters = {}, modules = {}, path = []) {
|
|
|
- if (!path.length) {
|
|
|
- wrapGetters(getters, getters, path, true)
|
|
|
+function initModule (store, path, module, hot) {
|
|
|
+ const isRoot = !path.length
|
|
|
+ const {
|
|
|
+ state,
|
|
|
+ actions,
|
|
|
+ mutations,
|
|
|
+ getters,
|
|
|
+ modules
|
|
|
+ } = module
|
|
|
+
|
|
|
+ // set state
|
|
|
+ if (!isRoot && !hot) {
|
|
|
+ const parentState = getNestedState(store.state, path.slice(0, -1))
|
|
|
+ if (!parentState) debugger
|
|
|
+ const moduleName = path[path.length - 1]
|
|
|
+ Vue.set(parentState, moduleName, state || {})
|
|
|
}
|
|
|
- if (!modules) {
|
|
|
- return getters
|
|
|
+
|
|
|
+ if (mutations) {
|
|
|
+ Object.keys(mutations).forEach(key => {
|
|
|
+ store.mutation(key, mutations[key], path)
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ if (actions) {
|
|
|
+ Object.keys(actions).forEach(key => {
|
|
|
+ store.action(key, actions[key], path)
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ if (getters) {
|
|
|
+ wrapGetters(store._wrappedGetters, getters, path)
|
|
|
+ }
|
|
|
+
|
|
|
+ if (modules) {
|
|
|
+ Object.keys(modules).forEach(key => {
|
|
|
+ initModule(store, path.concat(key), modules[key], hot)
|
|
|
+ })
|
|
|
}
|
|
|
- Object.keys(modules).forEach(key => {
|
|
|
- const module = modules[key]
|
|
|
- const modulePath = path.concat(key)
|
|
|
- if (module.getters) {
|
|
|
- wrapGetters(getters, module.getters, modulePath)
|
|
|
- }
|
|
|
- extractModuleGetters(getters, module.modules, modulePath)
|
|
|
- })
|
|
|
- return getters
|
|
|
}
|
|
|
|
|
|
-function wrapGetters (getters, moduleGetters, modulePath, force) {
|
|
|
+function wrapGetters (getters, moduleGetters, modulePath) {
|
|
|
Object.keys(moduleGetters).forEach(getterKey => {
|
|
|
const rawGetter = moduleGetters[getterKey]
|
|
|
- if (getters[getterKey] && !force) {
|
|
|
+ if (getters[getterKey]) {
|
|
|
console.error(`[vuex] duplicate getter key: ${getterKey}`)
|
|
|
return
|
|
|
}
|