diff --git a/README.md b/README.md index 893dc1a..8da96e2 100644 --- a/README.md +++ b/README.md @@ -277,6 +277,31 @@ class MyModule extends VuexModule { } ``` +If you would like to preserve the state e.g when loading in the state from [vuex-persist](https://www.npmjs.com/package/vuex-persist) + + +```diff +... + +-- @Module({ dynamic: true, store: store, name: 'mm' }) +++ @Module({ dynamic: true, store: store, name: 'mm', preserveState: true }) +class MyModule extends VuexModule { + +... +``` + +Or when it doesn't have a initial state and you load the state from the localStorage + + +```diff +... + +-- @Module({ dynamic: true, store: store, name: 'mm' }) +++ @Module({ dynamic: true, store: store, name: 'mm', preserveState: localStorage.getItem('vuex') !== null }) +class MyModule extends VuexModule { + +... +``` ### Accessing modules with NuxtJS There are many possible ways to construct your modules. Here is one way for drop-in use with NuxtJS (you simply need to add your modules to `~/utils/store-accessor.ts` and then just import the modules from `~/store`): diff --git a/package-lock.json b/package-lock.json index 31ee922..092264b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5042,6 +5042,12 @@ "locate-path": "^2.0.0" } }, + "flatted": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz", + "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==", + "dev": true + }, "flush-write-stream": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", @@ -7359,6 +7365,12 @@ "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", "dev": true }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, "lodash.template": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", @@ -7781,6 +7793,24 @@ "supports-color": "5.4.0" } }, + "mock-local-storage": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/mock-local-storage/-/mock-local-storage-1.1.11.tgz", + "integrity": "sha512-71sytP93tB0CkPbacafcP1iTVj9ssXU+ztRmx1MrS488JpO0az5d2sx+SNuvhGVSW56XO5M0f82uFhxteZEp9w==", + "dev": true, + "requires": { + "core-js": "^0.8.3", + "global": "^4.3.2" + }, + "dependencies": { + "core-js": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-0.8.4.tgz", + "integrity": "sha1-wiZl8eDRucPF4bCNq9HxCGleT88=", + "dev": true + } + } + }, "move-concurrently": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", @@ -13230,6 +13260,16 @@ "integrity": "sha512-ha3jNLJqNhhrAemDXcmMJMKf1Zu4sybMPr9KxJIuOpVcsDQlTBYLLladav2U+g1AvdYDG5Gs0xBTb0M5pXXYFQ==", "dev": true }, + "vuex-persist": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/vuex-persist/-/vuex-persist-2.2.0.tgz", + "integrity": "sha512-o/qbBeMcKZZqMvCXc7kfIew/5cjHxlP1f53rx5YYp3r2tk2kxXYK/UZumxKn7OXywlurl2r0mgkuBzH6nIWFjw==", + "dev": true, + "requires": { + "flatted": "^2.0.0", + "lodash.merge": "^4.6.2" + } + }, "watchpack": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz", diff --git a/package.json b/package.json index 913626c..68d5821 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,7 @@ "@types/mocha": "^5.2.5", "chai": "^4.2.0", "mocha": "^5.2.0", + "mock-local-storage": "^1.1.8", "nyc": "^13.2.0", "prettier": "^1.16.4", "rimraf": "^2.6.3", @@ -63,7 +64,8 @@ "typescript": "^3.5.3", "vue": "^2.6.10", "vuepress": "^1.0.3", - "vuex": "^3.1.1" + "vuex": "^3.1.1", + "vuex-persist": "^2.2.0" }, "dependencies": {}, "engines": { diff --git a/src/module/index.ts b/src/module/index.ts index f5f0e67..3ecd8ba 100644 --- a/src/module/index.ts +++ b/src/module/index.ts @@ -20,7 +20,8 @@ function registerDynamicModule(module: Mod, modOpt: DynamicModuleOpti modOpt.store.registerModule( modOpt.name, // TODO: Handle nested modules too in future - module + module, + { preserveState: modOpt.preserveState || false } ) } diff --git a/src/moduleoptions.ts b/src/moduleoptions.ts index 865373d..c06d3ca 100644 --- a/src/moduleoptions.ts +++ b/src/moduleoptions.ts @@ -33,10 +33,16 @@ export interface DynamicModuleOptions { */ name: string + /** + * If this is enabled it will preserve the state when loading the module + */ + preserveState?: boolean + /** * whether or not the module is namespaced */ namespaced?: boolean + /** * Whether to generate a plain state object, or a state factory for the module */ diff --git a/test/vuex-persist.ts b/test/vuex-persist.ts new file mode 100644 index 0000000..0ed4101 --- /dev/null +++ b/test/vuex-persist.ts @@ -0,0 +1,72 @@ +import { expect } from 'chai' +import 'mock-local-storage' +import Vue from 'vue' +import Vuex from 'vuex' +import { VuexPersistence } from 'vuex-persist' +import { Module, Mutation, VuexModule } from '..' +import { getModule } from '../src' + +Vue.use(Vuex) + +interface StoreType { + mm: MyModule +} + +localStorage.setItem( + 'vuex', + JSON.stringify({ + mm: { + count: 20 + } + }) +) + +let vuexLocal = new VuexPersistence({ + storage: localStorage +}) + +let store = new Vuex.Store({ + plugins: [vuexLocal.plugin] +}) + +@Module({ + dynamic: true, + namespaced: true, + store: store, + name: 'mm', + preserveState: localStorage.getItem('vuex') !== null +}) +class MyModule extends VuexModule { + count = 0 + + @Mutation + incrCount(delta: number) { + this.count += delta + } +} + +@Module({ dynamic: true, namespaced: true, store: store, name: 'msm' }) +class MySecondModule extends VuexModule { + count = 0 + + @Mutation + incrCount(delta: number) { + this.count += delta + } +} + +describe('state restored by vuex-persist', () => { + it('should restore state', function() { + const mm = getModule(MyModule) + mm.incrCount(5) + expect(mm.count).to.equal(25) + mm.incrCount(10) + expect(mm.count).to.equal(35) + + const msm = getModule(MySecondModule) + msm.incrCount(5) + expect(msm.count).to.equal(5) + msm.incrCount(10) + expect(msm.count).to.equal(15) + }) +})