@@ -21,6 +21,7 @@ class Store {
2121 this . _actions = Object . create ( null )
2222 this . _mutations = Object . create ( null )
2323 this . _wrappedGetters = Object . create ( null )
24+ this . _runtimeModules = Object . create ( null )
2425 this . _subscribers = [ ]
2526 this . _pendingActions = [ ]
2627
@@ -40,11 +41,11 @@ class Store {
4041 // init root module.
4142 // this also recursively registers all sub-modules
4243 // and collects all module getters inside this._wrappedGetters
43- initModule ( this , state , [ ] , options )
44+ installModule ( this , state , [ ] , options )
4445
4546 // initialize the store vm, which is responsible for the reactivity
4647 // (also registers _wrappedGetters as computed properties)
47- initStoreVM ( this , state , this . _wrappedGetters )
48+ resetStoreVM ( this , state )
4849
4950 // apply plugins
5051 plugins . concat ( devtoolPlugin ) . forEach ( plugin => plugin ( this ) )
@@ -72,11 +73,11 @@ class Store {
7273 console . error ( `[vuex] unknown mutation type: ${ type } ` )
7374 return
7475 }
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+ } )
7880 } )
79- this . _committing = false
8081 if ( ! payload || ! payload . silent ) {
8182 this . _subscribers . forEach ( sub => sub ( mutation , this . state ) )
8283 }
@@ -118,24 +119,32 @@ class Store {
118119 }
119120
120121 replaceState ( state ) {
121- this . _committing = true
122- this . _vm . state = state
123- this . _committing = false
122+ this . _withCommit ( ( ) => {
123+ this . _vm . state = state
124+ } )
124125 }
125126
126- registerModule ( path , module , hot ) {
127- this . _committing = true
127+ registerModule ( path , module ) {
128128 if ( typeof path === 'string' ) path = [ path ]
129129 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 )
133145 }
134146
135147 hotUpdate ( newOptions ) {
136- this . _actions = Object . create ( null )
137- this . _mutations = Object . create ( null )
138- this . _wrappedGetters = Object . create ( null )
139148 const options = this . _options
140149 if ( newOptions . actions ) {
141150 options . actions = newOptions . actions
@@ -151,26 +160,49 @@ class Store {
151160 options . modules [ key ] = newOptions . modules [ key ]
152161 }
153162 }
154- this . registerModule ( [ ] , options , true )
163+ resetStore ( this )
155164 }
156165
157166 onActionsResolved ( cb ) {
158167 Promise . all ( this . _pendingActions ) . then ( cb )
159168 }
169+
170+ _withCommit ( fn ) {
171+ const committing = this . _committing
172+ this . _committing = true
173+ fn ( )
174+ this . _committing = committing
175+ }
160176}
161177
162178function assert ( condition , msg ) {
163179 if ( ! condition ) throw new Error ( `[vuex] ${ msg } ` )
164180}
165181
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 ) {
167198 const oldVm = store . _vm
168199
169- // bind getters
200+ // bind store public getters
170201 store . getters = { }
202+ const wrappedGetters = store . _wrappedGetters
171203 const computed = { }
172- Object . keys ( getters ) . forEach ( key => {
173- const fn = getters [ key ]
204+ Object . keys ( wrappedGetters ) . forEach ( key => {
205+ const fn = wrappedGetters [ key ]
174206 // use computed to leverage its lazy-caching mechanism
175207 computed [ key ] = ( ) => fn ( store )
176208 Object . defineProperty ( store . getters , key , {
@@ -197,14 +229,14 @@ function initStoreVM (store, state, getters) {
197229 if ( oldVm ) {
198230 // dispatch changes in all subscribed watchers
199231 // 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+ } )
203235 Vue . nextTick ( ( ) => oldVm . $destroy ( ) )
204236 }
205237}
206238
207- function initModule ( store , rootState , path , module , hot ) {
239+ function installModule ( store , rootState , path , module , hot ) {
208240 const isRoot = ! path . length
209241 const {
210242 state,
@@ -218,7 +250,9 @@ function initModule (store, rootState, path, module, hot) {
218250 if ( ! isRoot && ! hot ) {
219251 const parentState = getNestedState ( rootState , path . slice ( 0 , - 1 ) )
220252 const moduleName = path [ path . length - 1 ]
221- Vue . set ( parentState , moduleName , state || { } )
253+ store . _withCommit ( ( ) => {
254+ Vue . set ( parentState , moduleName , state || { } )
255+ } )
222256 }
223257
224258 if ( mutations ) {
@@ -239,7 +273,7 @@ function initModule (store, rootState, path, module, hot) {
239273
240274 if ( modules ) {
241275 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 )
243277 } )
244278 }
245279}
0 commit comments