[Vuex] Vuex 5 · vuejs/rfcs · Discussion #270 (original) (raw)
I create a extension for pinia, maybe can add to this RFC?
pinia-di: DI(dependency-injection) for pinia, work with vue@3.
Why?
vuex
, pinia
, or this RFC for vuex5
, they all seem to have a common problem, that is reuse store
.
For example, i have ten same components in my page, they have the same data structure but independent state, it is very cumbersome to manage them in an array of a common store.
Another problem, for large project, i want to release the memory of state(auto unmount store) after the component unmount. If we manage that manually, it is cumbersome too.
Based on my previous project experience, i take the DI (dependency injection) and IOC(Inversion of Control) of Angular
into vue
, it work greet.
Core Concepts
Store Use
: Thereturn
of defineStore.Store Creator
: A function that return aStore Use
.InjectionContext
: The parameter that theStore Creator
will receive.
InjectionContext: { getStore, useStoreId, onUnmounted }
getStore
: Get other store that have been provided by parent component or self component.
import { InjectionContext } from 'pinia-di'; import { OtherStore } from './stores/other';
export const AppStore = ({ getStore }: InjectionContext) => { return defineStore('app', { state: {}, actions: { test() { const otherStore = getStore(OtherStore)(); console.log(otherStore.xx); } } }); }
useStoreId
: Because pinia
use id
to identify one store, but our Store Creator
maybe use multiple times, so we need a method useStoreId
to generate the unique id.
import { InjectionContext } from 'pinia-di'; export const TestStore = ({ useStoreId }: InjectionContext) => { return defineStore(useStoreId('test'), { state: {}, }); }
onUnmounted
: Bind a function that will be invoked when the store unmounted.
import { InjectionContext } from 'pinia-di'; export const TestStore = ({ onUnmounted }: InjectionContext) => { const useTestStore = defineStore(useStoreId('test'), { state: {}, actions: { dispose() { console.log('dispose'); } } });
onUnmounted(() => { useTestStore().dispose(); });
return useTestStore; }
Define Store Creator
stores/appStore.ts
import { defineStore } from 'pinia'; import { InjectionContext } from 'pinia-di';
export const AppStore = ({ useStoreId }: InjectionContext) => { return defineStore(useStoreId('main'), { state: {}, }); }
Provide Store
App.vue
Use Store
Component.vue
Store Out Of Componet
stores/messageStore.ts
import { defineStore } from 'pinia';
export const MessageStore = ({ useStoreId }: InjectionContext) => { return defineStore(useStoreId('message'), { state: {} }); }
export const useMessageStore = MessageStore();
App.vue
Component.vue
Get Other Stores In Sotre
stores/messageStore.ts
import { defineStore } from 'pinia'; import { useStoreId } from 'pinia-di';
export const MessageStore = ({ getStore, useStoreId }: InjectionContext) => { return defineStore(useStoreId('message'), { state: {}, actions: { test: () => { // get other store that parent component or self provided const appStore = getStore(AppStore); console.log(appStore.xxx); } } }); }
export const useMessageStore = MessageStore();
Store Onunmounted
stores/appStore.ts
import { defineStore } from 'pinia';
export const AppStore = ({ onUnmounted, useStoreId }: InjectionContext) => {
// define store, useStoreId('main') generate the unique id for per Store Instance
const useMainstore = defineStore(useStoreId('main'), {
state: {},
actions: {
dispose: () => {
//
}
}
});
onUnmounted(() => { useMainstore().dispose(); });
return useMainstore(); }
Store Tree
If same store creator
provided by more than one parent, the useStore
will get the nearest one.
ParentA.Vue
ParentB.Vue
Child.Vue
Use Component Provider
App.vue