gertqin / vuex-class-modules Goto Github PK
View Code? Open in Web Editor NEWTypescript class decorators for vuex modules
License: MIT License
Typescript class decorators for vuex modules
License: MIT License
after deciding to use vuex-class-modules this happened :
● Test suite failed to run
Jest encountered an unexpected token
This usually means that you are trying to import a file which Jest cannot parse, e.g. it's not plain JavaScript.
By default, if Jest sees a Babel config, it will use that to transform your files, ignoring "node_modules".
Here's what you can do:
• To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
• If you need a custom transformation specify a "transform" option in your config.
• If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.
You'll find more details and examples of these config options in the docs:
https://jestjs.io/docs/en/configuration.html
Details:
/Users/vandries/workspaces/rba.ui/node_modules/vuex-class-modules/lib/index.js:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){export { Action } from "./actions";
^^^^^^
SyntaxError: Unexpected token 'export'
2 | // import ... // removed
3 | // import ...// removed
> 4 | import { VuexModule, Module, Mutation, Action } from 'vuex-class-modules';
| ^
5 | import store from '../index';
6 |
7 | @Module
at ScriptTransformer._transformAndBuildScript (node_modules/@jest/transform/build/ScriptTransformer.js:537:17)
at ScriptTransformer.transform (node_modules/@jest/transform/build/ScriptTransformer.js:579:25)
the app works as expected
vue,typescript,vuex (default generated by vue cli)
Hello!
Using standard vuex i was able to create getters function with params. How i can reach this using vuex-class-modules?
I really like the way this feature looks. Unfortunately I can not use it as-is.
Afaics with vuex-class-modules
you always have to import the applications main vuex store object. When the application is composed from multiple packages and the store assembled with store.registerModule
, this is not possible.
Do you think there is a way to define the vuex module independently of the main store and register it later?
is it possible to use inheritance to reuse common logic between modules using this package?
When using the generateMutationSetters
option, for each state property a mutation is generated, that sets the property.
Those setter mutations are only available inside of actions, not when using the module instance directly.
Do you think we should allow access from the outside? Or would you say that it is a much better practice to only do changes in the actions?
I'm getting this error in nuxt
[nuxt] store/index.ts should export a method that returns a vuex instance.
How can i fix it?
Is there a way to use auto-generated mutations (with generateMutationSetters: true
option) from the module instance? In Vue component for example?
const userModule = new UserModule({ store, name: "user" });
userModule.firstName = value;
// OR
userModule.set__firstName(value)
Or they have to be explicitly defined in this case?
Error: [vuex-class-module]: A module with name 'appModule' already exists.
at VuexClassModuleFactory3.registerVuexModule (module-factory.js:137)
at new accessor (module.js:28)
at appModule.ts:66
When doing a hot-reload,the above gets logged and the hot-reload is aborted.
Im exporting the module like this: export const appModule = new AppModule({ store, name: 'appModule' })
Any idea how i can"supress" this error and make it replace the module correctly?
How can i use getters with some params?
For example, get getUserById(id: string)
, but TS says A 'get' accessor cannot have parameters
Hi,
I would like to throttle some Vuex actions, that shouldn't be performed more than once per 3 minutes. I am using lodash's throttle function like this:
@Module
class AccountsModule extends VuexModule {
private accounts = new Array<Account>()
@Mutation
private setAccounts(accounts: Array<Account>) {
this.accounts = accounts
}
@Action
public async fetchAccounts() {
this.fetchThrottled()
}
fetchThrottled = _.throttle(performFetchAccounts, 3 * 60 * 1000, { trailing: false })
performFetchAccounts() {
AccountsAPI.getAccounts().then(accounts => this.setAccounts(accounts))
}
}
Is there any way to simplify this call chain, so don't have to define 3 different functions for one throttled action or vuex-class-modules' internals forbids other way?
After digging into issue #6 a little more, I found the following problem. I have created a simple example in https://github.com/bodograumann/vuex-inject-modules-example.
When defining a class through:
import { decorate, inject, injectable } from "inversify";
import { RegisterOptions, Module, VuexModule } from "vuex-class-modules";
decorate(injectable(), VuexModule);
@injectable()
export default class VuexExampleModule extends VuexModule {
constructor(@inject("VuexModuleOptions") options: RegisterOptions) {
super(options);
}
get testString() {
return "foo bar";
}
}
inversify adds metadata to the class. In particular, calling
Reflect.getMetadata("inversify:tagged", VuexExampleModule);
gives
{ 0: [{ key: "inject", value: "VuexModuleOptions" }] }
Unfortunately, when now applying the @Module
decorator as well, the metadata is not there anymore:
[…]
@Module
@injectable()
export default class VuexExampleModule extends VuexModule {
constructor(@inject("VuexModuleOptions") options: RegisterOptions) {
[…]
Now the above reflection call returns undefined
.
I like this library, but I cannot to register the module as a namespace: false.
I saw registerVuexModule() in module-factory.ts and the namespaced value is hardcoded, but maybe there is some workaround?
Saw the latest release and just wanted to say...Thank YOU! THANK YOU for maintaining this library, thank you for supporting the community!
Currently the options: RegisterOptions
need to contain a name
. So if I want to use dependency injection, I will have to inject a different value into each module class.
For my usage of vuex-class-modules, where I only use the proxy objects directly, the name parameter is not important, apart from having to generate a unique vuex module. The best solution would of course be to just have Symbol()
as the module namespace, but that is completely incompatible with vuex I think.
So my suggestion would be to either
name
option to be left out. Then, if it is not provided, generate a unique random name.name
to be a function, which is called to generate the name. Then the user can decide for themself whether to use a random or deterministic name.Another thought is to somehow use the class name when generating the vuex module name.
I'm looking to use this to dynamically add / remove Vuex stores. Has anyone come across this?
Vuex has a unregisterModule
function for this purpose - just wondering the best way to use it with this library.
https://vuex.vuejs.org/guide/modules.html#dynamic-module-registration
Thanks!
import { VuexClassModuleFactory, ModuleOptions, IVuexModule } from "./module-factory";
import { VuexModule } from "./VuexModule";
type VuexModuleClass = new (...args: any[]) => VuexModule;
export function Module<T extends VuexModuleClass>(target: T): T;
export function Module(options?: ModuleOptions): ClassDecorator;
export function Module<T extends VuexModuleClass>(arg?: ModuleOptions | T): ClassDecorator | T {
if (typeof arg === "function") {
return moduleDecoratorFactory()(arg) as T;
} else {
return moduleDecoratorFactory(arg);
}
}
function moduleDecoratorFactory(moduleOptions?: ModuleOptions) {
return <TFunction extends Function>(constructor: TFunction): TFunction => {
const accessor: any = function(...args: any[]) {
const instance = new constructor.prototype.constructor(...args) as IVuexModule;
Object.setPrototypeOf(instance, accessor.prototype);
const factory = new VuexClassModuleFactory(constructor, instance, moduleOptions || {});
factory.registerVuexModule();
return factory.buildAccessor();
};
accessor.prototype = Object.create(constructor.prototype);
accessor.prototype.constructor = accessor;
return accessor;
};
}
what is the reason for using new constructor.prototype.constructor
to create instance but not new constructor
?
i am a beginner, a little confused.
Hi, first of all, thank you for the amazing job you have done with this library, it is saving the day in my frontend team in so many projects.
I know that this question could sounds hasty but, do you have any plan to support Vuex 4 and Vue 3 on the next releases?
Maybe I'm confused, but I didn't found any roadmap on this project.
This is not a bug, but a small problem I encountered myself, but I will encounter the cause of this problem, I think it may be due to
// register module (could be in any file)
This sentence is ambiguous, so please change it to
//suggest to write it in the store.js file'
When I write this code in the AppModule.ts file, I will be prompted Cannot read property 'state' of undefined
AppModule.ts file content
import {VuexModule, Module} from "vuex-class-modules"
@Module({generateMutationSetters: true})
export default class AppModule extends VuexModule {
name:string = ''
}
// register module (could be in any file)
import store from "./index"
export const appModule = new AppModule({store, name: 'app'})
And when I write this code into '@plugins/store/index', everything works fine
import Vue from 'vue'
import Vuex from 'vuex'
import AppModule from "@/plugins/store/AppModule"
import TalkModule from "@/plugins/store/TalkModule"
import UserModule from "@/plugins/store/UserModule"
Vue.use(Vuex)
const store = new Vuex.Store({
modules: {}
})
export const appModule = new AppModule({store, name: 'app'})
export const talkModule = new TalkModule({store, name: 'talk'})
export const userModule = new UserModule({store, name: 'user'})
export default store
I think the reason for this problem may be that you must instantiate the appModule before using it. If you write this paragraph in AppModule.ts, it will not be called, so you cannot instantiate the appModule object
Hi,
I'm completely stuck on an issue I encounter with passing multiple arguments through an action. I've tried my best to find a solution but my vuex/decorators experience is limited. Help is appreciated.
===My .ts file belonging to the vue component ===
function receives a (dynamic)number when clicking in a table and recieves a (dynamic) year when clicking.
@raceResultsModule.Action
loadRaceResults!: (year: any, round: any) => void;
getResults(round: number) {
this.loadRaceResults(this.year, round);
}
===My module .ts file with the action/axios call receives the passed dynamic values year and round===
@Action
async loadRaceResults(data: { year: number; round: number }) {
await axios
.get(`http://localhost:8000/api/f1/${year}/${round}/results.json`)
.then((response) => {
this.raceResults = response.data.MRData.RaceTable.Races;
})
.catch((error) => console.log(error));
}
If I console.log data I receive only one value(year) instead of two dynamic values(year + round). How can I accomplish this properly?
The sources are transpiled with a tsc module
target of es2015
.
This makes them unusable in a node app with only a typescript
setup (no webpack
or babel
):
./node_modules/vuex-class-modules/lib/index.js:1
export { Action } from "./actions";
^^^^^^
SyntaxError: Unexpected token 'export'
#46 Transpile to commonjs
modules in addition to es2015
.
the modules are dynamically loaded, nothing is being saved.
import { VuexModule, Module, Mutation, Action } from 'vuex-class-modules';
import store from '@/store';
@Module
export default class QuoteModule extends VuexModule {
}
export const quoteModule = new QuoteModule({ store, name: 'quote' });
const vuexLocal = new VuexPersistence({
storage: window.localStorage,
modules: ['quote'],
});
export default new Vuex.Store({
strict: true,
/*
Ideally if all your modules are dynamic
then your store is registered initially
as a completely empty object
*/
plugins: [vuexLocal.plugin],
});
Trying to use this module for share common logic
Found question #13 and it works, but with bug of initializing actions (and maybe mutations too)
export default class Collection extends VuexModule {
url = "/collection";
items = [];
@Action async getList() {
//...
}
}
@Module
export default class Projects extends Collection {
url = "/project";
@Action async getList() {
// change something
}
}
@Module
export default class Roads extends Collection {
url = "/road";
@Action async getList() {
// change something else
}
}
// init modules
import Projects from "./Projects";
export const projects = new Projects({ store, name: "projects" });
import Roads from "./Roads";
export const roads = new Roads({ store, name: "roads" });
And when I call projects/getList
it calls method from roads
.
I think problem is here:
vuex-class-modules/src/actions.ts
Line 9 in 2dab4e7
Child classes inherit this vuexModule.__actions
property, that's why Roads' methods overwrite Projects' one.
This is a feature request.
Currently, I'm using vuex-module-decorators
and looking for an alternative that supports dynamically managing multiple instances of same module definition. This is inherently impossible with vuex-module-decorators
which requires module name to be specified with the @Module
decorator in order to create accessor objects. Now that I found vuex-class-modules
can do that (nice!), I found a couple of crucial registerModule features are not exposed by vuex-class-modules
and wanted to leave a feedback.
From vuex docs:
registerModule(path: string | Array, module: Module, options?: Object)
Register a dynamic module.
options can havepreserveState: true
that allows to preserve the previous state. Useful with Server Side Rendering.
https://vuex.vuejs.org/api/#registermodule
https://vuex.vuejs.org/guide/modules.html#dynamic-module-registration
Here, following features are missing from the VuexClassModuleFactory of vuex-class-modules
:
Array<string>
as the module path to register nested modules{preserveState: true}
as an optionI'm especially looking for the latter because we use vuex-persist
plugin and need to specify preserveState
for each module that are previously persisted.
Thanks!
Hi, how i can pass parameters to getters ?
Trying to access vm:
this._vm.$socket.client.emit('SomeEvent', data);
Get error:
Property '_vm' does not exist on type 'MyModule'.ts(2339)
Any idea?
This minimum example does not work as expected:
import Vue from 'vue'
import Vuex from 'vuex'
import { VuexModule, Module, Mutation } from 'vuex-class-modules'
Vue.use(Vuex)
@Module
class Foo extends VuexModule {
value: string = 'abc'
@Mutation setValue(value: string) { this.value = value }
}
const store = new Vuex.Store({})
const foo = new Foo({ store, name: 'foo' })
foo.$watch(
f => f.value,
(value) => { console.log(value) } /// watch state changes and output the new value
)
foo.setBar('xyz')
Expected behavior:
Output with xyz
.
Actual behavior:
Output with undefined
.
I reviewed the code and found the cause may be that $watch
does not get namespaced state.
In module-factory.ts
:
accessorModule.$watch = (
fn: (arg: VuexModule) => any,
callback: (newValue: any, oldValue: any) => void,
options?: WatchOptions
) => {
store.watch(
(state: any, getters: any) => fn(this.buildThisProxy({ state, getters, useNamespaceKey: true })),
callback,
options
);
};
When calling this.buildThisProxy()
, it should pass in state: state[name]
instead.
Should I open a pull request for this?
I was wondering if it is possible to improve support for multi argument mutations.
At the moment this seems to be the only way of allowing multiple arguments:
@Mutation
public mutate(payload: { a: string; b: string }): void {
this.a = payload.a
this.b = payload.b
}
If possible, this would be better:
@Mutation
public mutate(a: string, b: string): void {
this.a = a
this.b = b
}
Hi,
thanks for this awsome library. I would like to use it with memoizee to get some TTL caching. I am trying to use it this way:
import memoize from "memoizee"
import { VuexModule, Module, Mutation, Action } from "vuex-class-modules"
import { Backend } from "@/store/modules/backends/models"
import { BackendsAPI } from "./api"
import store from "@/store"
@Module
class BackendsModule extends VuexModule {
private _backends: Array<Backend> = []
private _getBackendsMemoized = memoize(BackendsAPI.getBackends)
public get backends() {
return this._backends
}
@Mutation
private setBackends(backends: Array<Backend>) {
this._backends = backends
}
@Action
public async fetchBackends() {
const backends = await this._getBackendsMemoized()
this.setBackends(backends)
}
}
However, I get an error saying: TypeError: this._getBackendsMemoized is not a function
. Any ideas how can I use memoization in a smart way with vuex-class-modules?
As documented at https://vuex.vuejs.org/api/#watch, vuex allows to watch the state without having a vue component. E.g.
store.watch(
function(state, getters) {
return getters.loggedIn;
},
loggedIn => {
…
}
);
would execute a function every time the login state changes.
Afaics this is currently not possible when using vuex-class-modules. It would be nice to have a watch
method where the callback is not called with state
and getters
, but with the vuex module. Maybe it should be called $watch
to prevent naming conflicts.
(Note: The second parameter getters
is not given with the latest vuex
release v3.0.1. You’ll need the master
branch for that.)
Is there any kind of provision to have sub modules inside of a module?
Like in the original Vuex we have
const ModuleA {
state: {...},
mutations: {...},
actions: {...},
modules: {
subA: ModuleSubA
}
}
In vuex-class-modules, maybe something like this
class ModuleA {
subA = createSubModule(ModuleSubA);
}
Please, specify if something like that already exists, or any workaround would also work
Hey there,
I couldn't find anything on SO so I'd like to ask here about. I recently moved from plain JS to TS and therefore started using vuex-class-modules
. However, all of my tests using VueX that were working previously just stopped working with vuex-class-modules
.
Is there anything special to take care about using vuex-class-modules
?
I'm running tests on Jest
.
After some more digging into vuex-class-modules
I have to extend my question.
Using plain Vuex actions get triggered in my test and do what they are supposed to do. However, when I set up my test with vuex-class-module
, by defining a VuexModule
and putting in everything I need, my test still breaks. Is there by any chance some kind of 'how to' for working with vuex-class-module
?
You define the type of an action method as TypedPropertyDescriptor<(arg?: any) => Promise<void>>'
.
I think there should be more options.
Promise<any>
.I was looking to create a decorator to automatically call module methods on mounting a module, so I forked the repo here and added some lines to src/module-factory
and src/index.ts
. I also added src/onload.ts
, which is basically an adaptation of src/actions.ts
.
My changes basically add support for an @Onload
method decorator and has worked in my tests. I was hoping that someone could review this as I believe it adds an interesting feature.
Thanks.
Is it possible to define an Action that gets wrapped in another function?
Example of wrapping an action using vuexfire:
actions: {
bindTodos: firestoreAction(({ bindFirestoreRef }) => {
// return the promise returned by `bindFirestoreRef`
return bindFirestoreRef('todos', db.collection('todos'))
}),
}
I've tried a few different ways.
@Action
bindTodos1 = firestoreAction(({ bindFirestoreRef }) => {
// return the promise returned by `bindFirestoreRef`
return bindFirestoreRef('todos', db.collection('todos'))
})
// ^ Unable to resolve signature of property decorator when called as an expression. ts(1240)
@Action
bindTodos2 () {
return firestoreAction(({ bindFirestoreRef }) => {
return bindFirestoreRef('todos', db.collection('todos'))
})
}
// ^ compiles, and seems to execute, but does not update 'todos' state property
bindTodos3 = firestoreAction(({ bindFirestoreRef }) => {
return bindFirestoreRef('todos', db.collection('todos'))
})
@Action
bindTodos4 () {
return this.bindTodos3()
}
Is there a specific syntax or even a workaround to get a firestoreAction into a VuexModule ?
I'm having trouble using both vuex-class-modules and vue-router lazy loading at the same time.
For reference- here is a commit of the project showing the issue-
https://github.com/danieleades/lazy-load-issue
router.ts
{
path: '/transactions',
name: 'transactions',
component: () => import(/* webpackChunkName: "transactions" */ './views/Transactions.vue'),
},
const transactionsModule = new TransactionsModule({ store, name: 'transactions' });
export { transactionsModule };
import { Component, Vue } from 'vue-property-decorator';
import { transactionsModule } from '@/store/transactions';
@Component
export default class TransactionsTable extends Vue {
get transactions() {
return transactionsModule.transactions;
}
}
any ideas? This library is amazing, please don't make me go back to static, stringly-typed modules!
Hi this project looks great, just wondered if before building this you saw this project https://championswimmer.in/vuex-module-decorators/ ?
If you did, may I ask how does your project differ/ what are the benefits? Just trying to understand the differences before I select one to go with.
Thanks again
I'm having problems using the vuex class modules with InversifyJS.
From the inversify docs I took
import { decorate, injectable } from "inversify";
decorate(injectable(), VuexModule);`
I’m not quite sure which order of the decorators is better, but @Module
first seems sensible. I have implemented the feature #5 and added a test using InversifyJS in bodograumann/vuex-class-modules#inversify.
import { Module, VuexModule, RegisterOptions } from "../src";
import Vuex from "vuex";
import Vue from "vue";
import { Container, decorate, injectable, inject } from "inversify";
import "reflect-metadata";
Vue.use(Vuex);
const store = new Vuex.Store<any>({});
decorate(injectable(), VuexModule);
@injectable()
@Module
class MyModule extends VuexModule {
constructor(
@inject("Options") options: (className: string) => RegisterOptions
) {
super(options);
}
foo = {
text: "some text"
};
bar = 1;
}
const container = new Container();
container
.bind<(className: string) => RegisterOptions>("Options")
.toConstantValue((className: string) => ({ store, name: "myModule" }));
const myModule = container.resolve(MyModule);
test("instance of", () => {
expect(myModule instanceof MyModule).toBe(true);
expect(myModule instanceof VuexModule).toBe(true);
});
It fails with:
The number of constructor arguments in the derived class accessor must be >= than the number of constructor arguments of its base class.
Is it possible that @Module
is not retaining the @inject
annotation? In that case I thought applying @Module
after @injectable()
would help, or at least git a different error, but nothing changes.
Hi,
It would be interesting to allow the composition of each part of a module: State, Getters, Mutations, and Actions as different composed class like this example below.
class UserState {
firstName = "Foo";
lastName = "Bar";
myFookingMap = new Map<String, NodeModel>();
constructor() {
this.myFookingMap.set("a", new NodeModel("a", "yehhhh"));
this.myFookingMap.set("b", new NodeModel("b", "cachouu"));
}
}
class UserMutation {
constructor(private userState: UserState) {}
@Mutation
setFirstName(firstName: string) {
this.userState.firstName = firstName;
}
@Mutation
setLastName(lastName: string) {
this.userState.lastName = lastName;
}
@Mutation
setMap() {
this.userState.myFookingMap.set("c", new NodeModel("c", "fiou"))
this.userState.myFookingMap.get("a")!.name = "superr"
}
}
class UserAction {
constructor(private userState: UserState, private mutation: UserMutation) {}
@Action
async loadUser() {
this.mutation.setFirstName("yao");
this.mutation.setLastName("yeh");
}
}
@Module
export class UserModule extends VuexModule {
state = new UserState();
mutation = new UserMutation(this.state);
actions = new UserAction(this.state, this.mutation);
// getters
get fullName() {
return this.state.firstName + " " + this.state.lastName;
}
}
Do you think you can implement such a feature??
It would allow doing abstraction on each different part of a store, and thus for example make UserMutation
extends from an interface or a class, and the same for UserAction
etc...
Futhermore it would allow sharing parts (action, mutation, state, getters) in different modules, as below:
export const projectResourceStore = new Module({
namespaced: true,
state: ResourceState,
getters: ResourceGetter,
mutations: ResourceMutation,
actions: ProjectResourceAction,
});
export const homeResourceStore = new Module({
namespaced: true,
state: ResourceState,
getters: ResourceGetter,
mutations: ResourceMutation,
actions: HomeResourceAction,
});
Thanks!
Hope you can do something @gertqin ! (what do you think in therm of complexity to implement such a feature?)
for example, i want to clear the state on logout.
how can i do this for all modules within the store?
Apologies for asking questions here.. and hoping for just pointers to point me in the right direction. If there is a better place to ask this, I'm more than happy to do that.
Just guidelines around loading initial state. Most of the default state assignments work, but one needs to come from a service. Would I just create an action and somehow trigger that on start someplace to load a value from a service, and then set a state property on my store?
I've got a module that handles behavior for a drop down context selector. This module is not aware of other modules. I've got a second module that basically wants to update parts of ITS state based on value set in the dropdown selector.
Pseudo code looks like this
Module1 -> SelectedContext
then
Module2 -> (when selected context changes) -> load data from a service, and set state value
I've tried lots of things for this one, and the thing that seems the closest to working, but doesnt actually work was
Create a watcher in the constructor of module2 that watches values for the SelectedContext. Then when it changes, fetch data and set value. I can see it executing every part of the code like I'd expect, but I don't see the UI reflecting the value that gets set when the context changes.
Hello!
I'm using your library inside an electron app built with Vue. I need to persist the state of the vuex store. To achieve this i tried saving the vuex state to a json file, using a vuex plugin. However, when i restore the state, on app launch, i get an error saying Error: [vuex-class-module]: A module with name 'myModule' already exists.
.
I'm pretty sure the Error originates from here:
vuex-class-modules/src/module-factory.ts
Line 173 in 61b18a4
I'm mainly wondering what the best way to solve this problem is. I was looking through the vuex docs and found a flag for registerModule
called preserveState
, do you think it would solve the problem if it was passed at registration time?
Hello, and thatnks for that package.
There is a comment on persistence.
#24
State persisted only before the page reloaded.
After that, it throws an error
vue-devtools Detected Vue v2.6.14
{FormWithVerification: accessor {SET_STEP: ...}
{testVal_1: 'original_val'} // call getter
// call action with mutation within
{testVal_1: 'mutated_val'} // call getter
// RELOAD PAGE OR REOPEN TAB (SPA)
{FormWithVerification: accessor {SET_STEP: ...} // same
{testVal_1: undefined} // call getter
// call action with mutation within throws
unknown action type: FormWithVerificationModule/changeVal
{testVal_1: undefined} // call getter
I also see state in dev tools, BUT, getters are removed / actions.
Sate not persisted nor dynamic modules registered again.
Its like they were loaded only on the first-page load.
"vue": "^2.6.14",
"vue-class-component": "^7.2.3",
"vue-property-decorator": "^9.1.2",
"vuex": "^3.0.1",
"vuex-class": "^0.3.2",
"vuex-class-modules": "^1.3.0",
"vuex-multi-tab-state": "^1.0.16",
"vuex-persistedstate": "^3.2.0",
import Vuex, {ModuleTree} from 'vuex';
import Vue from 'vue';
'use strict';
import createPersistedState from 'vuex-persistedstate';
import createMultiTabState from 'vuex-multi-tab-state';
import SecureLS from 'secure-ls';
const encryptedLocalStorage = new SecureLS(
{
encodingType: 'aes',
encryptionSecret: '****',
isCompression: false,
},
);
const plugins = [
createMultiTabState(),
createPersistedState({
storage: {
getItem: key => encryptedLocalStorage.get(key),
setItem: (key, value) => encryptedLocalStorage.set(key, value),
removeItem: key => encryptedLocalStorage.remove(key),
},
}),
];
export default plugins;
Vue.use(Vuex);
const store = new Vuex.Store({
strict: 'production' !== process.env.NODE_ENV,
devtools: 'production' !== process.env.NODE_ENV,
modules,
plugins,
},
);
export default store;
So, plugins
createMultiTabState(),
createPersistedState()
are not working, reloading page does not register modules again and makes them unavailable for usage.
state resets, getters / actions removed.
Trying to register module again it says module already exists.
Any advice, guidance appreciated. Maybe add some docs on that.
Because cant find in this package such must have feature.
Was thinking to add some beforeDestroy(){} listener or something that will save whole state in local storage, but thats definetely not enough, we need to serialize, encrypt, then restore it back when tab, browser opened or page reloaded.
Thanks!
Within vanilla Vuex we have extension like
// vuex-shims.d.ts
declare module 'vuex/types' {
interface Store<S> {
$api: ServiceFactory;
}
}
And access it in actions like
async [ActionNames.DoSomething]() {
await this.$api.doSomething(); // 'this' known as Store<R> type and $api is registered extension.
}
But module of 'vuex-class-modules' has no 'this' as Store type. How to access $api extension?
Tried to make extended subclass of VuexModule like
export class AugmentedVuexModule extends VuexModule
{
// eslint-disable-next-line @typescript-eslint/no-explicit-any
protected store: Store<any>;
constructor(options: RegisterOptions)
{
super(options);
this.store = options.store;
}
}
Usage:
@Action
async doSomething()
{
await this.store.$api.doSomething();
}
But it cause an error:
/ -> error during render
RangeError: Maximum call stack size exceeded
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.