@@ -21,6 +21,7 @@ class Store {
21
21
this . _actions = Object . create ( null )
22
22
this . _mutations = Object . create ( null )
23
23
this . _wrappedGetters = Object . create ( null )
24
+ this . _runtimeModules = Object . create ( null )
24
25
this . _subscribers = [ ]
25
26
this . _pendingActions = [ ]
26
27
@@ -40,11 +41,11 @@ class Store {
40
41
// init root module.
41
42
// this also recursively registers all sub-modules
42
43
// and collects all module getters inside this._wrappedGetters
43
- initModule ( this , state , [ ] , options )
44
+ installModule ( this , state , [ ] , options )
44
45
45
46
// initialize the store vm, which is responsible for the reactivity
46
47
// (also registers _wrappedGetters as computed properties)
47
- initStoreVM ( this , state , this . _wrappedGetters )
48
+ resetStoreVM ( this , state )
48
49
49
50
// apply plugins
50
51
plugins . concat ( devtoolPlugin ) . forEach ( plugin => plugin ( this ) )
@@ -72,11 +73,11 @@ class Store {
72
73
console . error ( `[vuex] unknown mutation type: ${ type } ` )
73
74
return
74
75
}
75
- this . _committing = true
76
- entry . forEach ( function commitIterator ( handler ) {
77
- handler ( payload )
76
+ this . _withCommit ( ( ) => {
77
+ entry . forEach ( function commitIterator ( handler ) {
78
+ handler ( payload )
79
+ } )
78
80
} )
79
- this . _committing = false
80
81
if ( ! payload || ! payload . silent ) {
81
82
this . _subscribers . forEach ( sub => sub ( mutation , this . state ) )
82
83
}
@@ -118,24 +119,32 @@ class Store {
118
119
}
119
120
120
121
replaceState ( state ) {
121
- this . _committing = true
122
- this . _vm . state = state
123
- this . _committing = false
122
+ this . _withCommit ( ( ) => {
123
+ this . _vm . state = state
124
+ } )
124
125
}
125
126
126
- registerModule ( path , module , hot ) {
127
- this . _committing = true
127
+ registerModule ( path , module ) {
128
128
if ( typeof path === 'string' ) path = [ path ]
129
129
assert ( Array . isArray ( path ) , `module path must be a string or an Array.` )
130
- initModule ( this , this . state , path , module , hot )
131
- initStoreVM ( this , this . state , this . _wrappedGetters )
132
- this . _committing = false
130
+ this . _runtimeModules [ path . join ( '.' ) ] = module
131
+ installModule ( this , this . state , path , module )
132
+ // reset store to update getters...
133
+ resetStoreVM ( this , this . state )
134
+ }
135
+
136
+ unregisterModule ( path ) {
137
+ if ( typeof path === 'string' ) path = [ path ]
138
+ assert ( Array . isArray ( path ) , `module path must be a string or an Array.` )
139
+ delete this . _runtimeModules [ path . join ( '.' ) ]
140
+ this . _withCommit ( ( ) => {
141
+ const parentState = getNestedState ( this . state , path . slice ( 0 , - 1 ) )
142
+ Vue . delete ( parentState , path [ path . length - 1 ] )
143
+ } )
144
+ resetStore ( this )
133
145
}
134
146
135
147
hotUpdate ( newOptions ) {
136
- this . _actions = Object . create ( null )
137
- this . _mutations = Object . create ( null )
138
- this . _wrappedGetters = Object . create ( null )
139
148
const options = this . _options
140
149
if ( newOptions . actions ) {
141
150
options . actions = newOptions . actions
@@ -151,26 +160,49 @@ class Store {
151
160
options . modules [ key ] = newOptions . modules [ key ]
152
161
}
153
162
}
154
- this . registerModule ( [ ] , options , true )
163
+ resetStore ( this )
155
164
}
156
165
157
166
onActionsResolved ( cb ) {
158
167
Promise . all ( this . _pendingActions ) . then ( cb )
159
168
}
169
+
170
+ _withCommit ( fn ) {
171
+ const committing = this . _committing
172
+ this . _committing = true
173
+ fn ( )
174
+ this . _committing = committing
175
+ }
160
176
}
161
177
162
178
function assert ( condition , msg ) {
163
179
if ( ! condition ) throw new Error ( `[vuex] ${ msg } ` )
164
180
}
165
181
166
- function initStoreVM ( store , state , getters ) {
182
+ function resetStore ( store ) {
183
+ store . _actions = Object . create ( null )
184
+ store . _mutations = Object . create ( null )
185
+ store . _wrappedGetters = Object . create ( null )
186
+ const state = store . state
187
+ // init root module
188
+ installModule ( store , state , [ ] , store . _options , true )
189
+ // init all runtime modules
190
+ Object . keys ( store . _runtimeModules ) . forEach ( key => {
191
+ installModule ( store , state , key . split ( '.' ) , store . _runtimeModules [ key ] , true )
192
+ } )
193
+ // reset vm
194
+ resetStoreVM ( store , state )
195
+ }
196
+
197
+ function resetStoreVM ( store , state ) {
167
198
const oldVm = store . _vm
168
199
169
- // bind getters
200
+ // bind store public getters
170
201
store . getters = { }
202
+ const wrappedGetters = store . _wrappedGetters
171
203
const computed = { }
172
- Object . keys ( getters ) . forEach ( key => {
173
- const fn = getters [ key ]
204
+ Object . keys ( wrappedGetters ) . forEach ( key => {
205
+ const fn = wrappedGetters [ key ]
174
206
// use computed to leverage its lazy-caching mechanism
175
207
computed [ key ] = ( ) => fn ( store )
176
208
Object . defineProperty ( store . getters , key , {
@@ -197,14 +229,14 @@ function initStoreVM (store, state, getters) {
197
229
if ( oldVm ) {
198
230
// dispatch changes in all subscribed watchers
199
231
// to force getter re-evaluation.
200
- store . _committing = true
201
- oldVm . state = null
202
- store . _committing = false
232
+ store . _withCommit ( ( ) => {
233
+ oldVm . state = null
234
+ } )
203
235
Vue . nextTick ( ( ) => oldVm . $destroy ( ) )
204
236
}
205
237
}
206
238
207
- function initModule ( store , rootState , path , module , hot ) {
239
+ function installModule ( store , rootState , path , module , hot ) {
208
240
const isRoot = ! path . length
209
241
const {
210
242
state,
@@ -218,7 +250,9 @@ function initModule (store, rootState, path, module, hot) {
218
250
if ( ! isRoot && ! hot ) {
219
251
const parentState = getNestedState ( rootState , path . slice ( 0 , - 1 ) )
220
252
const moduleName = path [ path . length - 1 ]
221
- Vue . set ( parentState , moduleName , state || { } )
253
+ store . _withCommit ( ( ) => {
254
+ Vue . set ( parentState , moduleName , state || { } )
255
+ } )
222
256
}
223
257
224
258
if ( mutations ) {
@@ -239,7 +273,7 @@ function initModule (store, rootState, path, module, hot) {
239
273
240
274
if ( modules ) {
241
275
Object . keys ( modules ) . forEach ( key => {
242
- initModule ( store , rootState , path . concat ( key ) , modules [ key ] , hot )
276
+ installModule ( store , rootState , path . concat ( key ) , modules [ key ] , hot )
243
277
} )
244
278
}
245
279
}
0 commit comments