Open sniperadmin opened 4 years ago
@/store/counter.ts
import { Module, Action, Mutation, VuexModule } from 'vuex-module-decorators'
@Module({ name: 'counter', stateFactory: true, namespaced: true, }) export default class Counter extends VuexModule { public counter: number = 0
get getCounter() { return this.counter }
@Mutation INCREMENT_COUNTER() { this.counter++ }
@Mutation DECR_COUNTER() { this.counter-- }
@Action increment({ commit }) { commit('INCREMENT_COUNTER') }
@Action decr({ commit }) { commit('DECR_COUNTER') } }
I created a store accessor:
`@/utils/store-accessor`
```ts
import { Store } from 'vuex'
import { getModule } from 'vuex-module-decorators'
import Counter from '@/store/counter'
let counterStore: Counter
function initialiseStores(store: Store<any>) {
counterStore = getModule(Counter, store)
}
export { initialiseStores, counterStore }
@/store/index.ts
import { Store } from 'vuex'
import { initialiseStores } from '@/utils/store-accessor'
const initializer = (store: Store
export const plugins = [initializer]
export * from '@/utils/store-accessor'
3. In the vue component:
`example.vue`
```vue.js
import { counterStore } from '@/store'
@Component({})
export default class Index extends Vue {
public testMethod() {
console.log(counterStore.getCounter)
}
mounted() {
this.testMethod()
}
}
This approach works so far, but need to find a god way for testing it using jest...
Approach2 (Works with nuxt-ts so far)
This shares your data between requests. I already experienced all the pain with this method. This is noticeable when there are many users.
appreciate your contributions, I will check the open issues... this project is still a POC, so i won't get worried about users for now,.. but i need to continue, so far, If there is a better solution, it would be great
I'm using this:
The point is to do this as a plugin and inject in this.$storeModules
.
In fact, working with vuex-module-decorators
for more than a year, I would not advise using the it, it creates quite a few restrictions.
Didn't try that before, let me check... 🚀
@iliyaZelenko ... Do I have to define a storeAppContextInterface
?
import QuestionsStoreMod from '~/store/QuestionsStoreMod'
import AdvertisingStoreMod from '~/store/AdvertisingStoreMod'
import MainPageStoreMod from '~/store/MainPageStoreMod'
import PostStoreMod from '~/store/PostStoreMod'
import ToastsStoreMod from '~/store/ToastsStoreMod'
import AuthStoreMod from '~/store/AuthStoreMod'
import PostCommentsStoreMod from '~/store/PostCommentsStoreMod'
import DiaryStoreMod from '~/store/DiaryStoreMod'
import CommunityStoreMod from '~/store/CommunityStoreMod'
import ModerationStoreMod from '~/store/ModerationStoreMod'
import UIStoreMod from '~/store/UIStoreMod'
import MessengerStoreMod from '~/store/MessengerStoreMod'
export interface StoreAppContextInterface {
auth: AuthStoreMod
questions: QuestionsStoreMod
advertising: AdvertisingStoreMod
mainPage: MainPageStoreMod
post: PostStoreMod
postComments: PostCommentsStoreMod
toasts: ToastsStoreMod
diary: DiaryStoreMod
community: CommunityStoreMod
moderation: ModerationStoreMod
UI: UIStoreMod
messenger: MessengerStoreMod
}
Tried to be simple:
// `@/plugins/store.ts`
import Counter from '@/store/counter'
import { getModule } from 'vuex-module-decorators';
interface StoreAppContextInterface {
counter: Counter
}
export default (ctx, Inject) => {
const storeModulesClasses = {
counter: Counter
}
const storeModule = {} as StoreAppContextInterface
for (const key in storeModulesClasses) {
storeModule[key] = getModule(storeModulesClasses[key], ctx.store)
Object.setPrototypeOf(storeModule[key], {
appContext: ctx
})
}
Inject('storeModules', storeModule)
ctx.$storeModules = storeModule
}
in my store dir => there is only the module file counter.ts
still it does not inject it properly
This approach worked well for me. It's a bit nicer too IMO (you need to translate the page from Japanese): https://qiita.com/yoshinbo/items/70f109db7c3de4b4a99f
@justinIs classic mode is deprecated
Tried to be simple
Thanks a lot, @sniperadmin. Here is version with all the missing types:
// `@/plugins/store.ts`
import type { Context } from '@nuxt/types'
import type { Inject } from '@nuxt/types/app'
import { getModule } from 'vuex-module-decorators'
import ExampleModule from '@/store/example'
export interface StoreAppContextInterface {
data: ExampleModule
}
declare module 'vue/types/vue' {
// adds this.$storeModules inside Vue components
interface Vue {
$storeModules: StoreAppContextInterface
}
}
export default (ctx: Context, inject: Inject): void => {
const storeModulesClasses = {
data: ExampleModule,
}
const storeModules = {} as StoreAppContextInterface
const keys = Object.keys(storeModulesClasses) as Array<
keyof typeof storeModulesClasses
>
keys.forEach((key: keyof typeof storeModulesClasses) => {
storeModules[key] = getModule(storeModulesClasses[key], ctx.store)
Object.setPrototypeOf(storeModules[key], {
appContext: ctx,
})
})
// inject doesn't inject in context but in context.app
inject('storeModules', storeModules)
// if there will be a need to access it directly, we can uncomment below
// ctx.$storeModules = storeModules
}
UPD: sadly Object.setPrototypeOf
does not actually work, store modules will not have access to appContext
this way with vuex-module-decorators
. It looks like instances of classes representing Vuex modules are then destructured and composed to some other objects internally loosing access to the previous this
.
Note
All possible trials to use vuex decorators will be recorded on here.
Approach 1 (crashes with nuxt [ Reference Error: Cannot access 'store' before initialization ])
@/store/index.ts
@/store/modules/counter
in the vue component:
Note: This approach works with Vue
The rest of approaches will be documented on here