diff --git a/docs/en/api.md b/docs/en/api.md index 63df8a607..28099f751 100644 --- a/docs/en/api.md +++ b/docs/en/api.md @@ -156,10 +156,12 @@ const store = new Vuex.Store({ ...options }) Most commonly used in plugins. [Details](plugins.md) -- **`registerModule(path: string | Array, module: Module)`** +- **`registerModule(path: string | Array, module: Module, options?: Object)`** Register a dynamic module. [Details](modules.md#dynamic-module-registration) + `options` can have `preserveState: true` that allows to preserve the previous state. Useful with Server Side Rendering. + - **`unregisterModule(path: string | Array)`** Unregister a dynamic module. [Details](modules.md#dynamic-module-registration) diff --git a/docs/en/modules.md b/docs/en/modules.md index ea8c876f6..36c2ffe2c 100644 --- a/docs/en/modules.md +++ b/docs/en/modules.md @@ -269,6 +269,8 @@ Dynamic module registration makes it possible for other Vue plugins to also leve You can also remove a dynamically registered module with `store.unregisterModule(moduleName)`. Note you cannot remove static modules (declared at store creation) with this method. +It may be likely that you want to preserve the previous state when registering a new module, such as preserving state from a Server Side Rendered app. You can do achieve this with `preserveState` option: `store.registerModule('a', module, { preserveState: true })` + ### Module Reuse Sometimes we may need to create multiple instances of a module, for example: diff --git a/src/store.js b/src/store.js index db8d1cb8b..8630b9e68 100644 --- a/src/store.js +++ b/src/store.js @@ -161,7 +161,7 @@ export class Store { }) } - registerModule (path, rawModule) { + registerModule (path, rawModule, options = {}) { if (typeof path === 'string') path = [path] if (process.env.NODE_ENV !== 'production') { @@ -170,7 +170,7 @@ export class Store { } this._modules.register(path, rawModule) - installModule(this, this.state, path, this._modules.get(path)) + installModule(this, this.state, path, this._modules.get(path), options.preserveState) // reset store to update getters... resetStoreVM(this, this.state) } diff --git a/test/unit/modules.spec.js b/test/unit/modules.spec.js index 1d9c8d688..a778ac3f2 100644 --- a/test/unit/modules.spec.js +++ b/test/unit/modules.spec.js @@ -80,6 +80,28 @@ describe('Modules', () => { store.commit('a/foo') expect(mutationSpy).toHaveBeenCalled() }) + + it('dynamic module registration preserving hydration', () => { + const store = new Vuex.Store({}) + store.replaceState({ a: { foo: 'state' }}) + const actionSpy = jasmine.createSpy() + const mutationSpy = jasmine.createSpy() + store.registerModule('a', { + namespaced: true, + getters: { foo: state => state.foo }, + actions: { foo: actionSpy }, + mutations: { foo: mutationSpy } + }, { preserveState: true }) + + expect(store.state.a.foo).toBe('state') + expect(store.getters['a/foo']).toBe('state') + + store.dispatch('a/foo') + expect(actionSpy).toHaveBeenCalled() + + store.commit('a/foo') + expect(mutationSpy).toHaveBeenCalled() + }) }) // #524 diff --git a/types/index.d.ts b/types/index.d.ts index f482095c8..f1fa8514f 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -20,8 +20,8 @@ export declare class Store { subscribe

(fn: (mutation: P, state: S) => any): () => void; watch(getter: (state: S) => T, cb: (value: T, oldValue: T) => void, options?: WatchOptions): () => void; - registerModule(path: string, module: Module): void; - registerModule(path: string[], module: Module): void; + registerModule(path: string, module: Module, options?: ModuleOptions): void; + registerModule(path: string[], module: Module, options?: ModuleOptions): void; unregisterModule(path: string): void; unregisterModule(path: string[]): void; @@ -96,6 +96,10 @@ export interface Module { modules?: ModuleTree; } +export interface ModuleOptions{ + preserveState?: boolean +} + export interface GetterTree { [key: string]: Getter; } diff --git a/types/test/index.ts b/types/test/index.ts index 63c42ccff..95c73884f 100644 --- a/types/test/index.ts +++ b/types/test/index.ts @@ -200,6 +200,10 @@ namespace RegisterModule { state: { value: 2 } }); + store.registerModule(["a", "b"], { + state: { value: 2 } + }, { preserveState: true }); + store.unregisterModule(["a", "b"]); store.unregisterModule("a"); }