[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

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