Registry stores
Уточнения по работе реестра со сторами и их расширению
Utils
Утилиты берут инстанс pinia из RegistryContext.$pinia, инжект pinia происходит в nuxt модуле
useStoreWrapper
Полный аналог useRegistryWrapper, но в качестве второго аргумента передается DefineStoreOptions
useStoreSetupWrapper
Идентично useStoreWrapper, но для setup функций сторов.
defineRegistryStore
Полный аналог defineRegistryItem, но в качестве второго аргумента передается DefineStoreOptions
defineRegistrySetupStore
Идентично defineRegistryStore, но для setup функций сторов.
defineDefaultStore
Утилита сугубо для более простой типизации DefineStoreOptions, возвращает переданный аргумент без изменений
extendStore
Утилита для мержа двух DefineStoreOptions, приоритет за вторым аргументом
extendSetupStore
Схоже с extendStore, но для setup функций сторов.
Не стоит заменять состояние из исходного стора, т.к. исходная setup функция может на него полагаться
Usage
Шаг 1 (Описание зависимости)
Т.к. pinia store сложнее обычных зависимостей, приходится тщательнее типизировать код
import {
type ExtractId,
type ExtractState,
type ExtractGetters,
type ExtractActions,
type StoreRegistryKey,
defineDefaultStore,
useStoreWrapper,
setActiveRegistry,
} from '@/modules/registry';
// Хелпер сугубо для правильной типизации
// т.к. если нужен стор в shared, у него есть какое-то изначальное наполнение
// мы задаём это самое дефолтное хранилище которое опционально в дальнейшем
// можно расширить в проектах
export const defaultStore = defineDefaultStore({
id: 'example',
state: () => ({
foo: 'foo',
bar: 123,
}),
getters: {
fooBar(state) {
return state.foo + state.bar;
},
},
});
// Шаблонный код для дальнейшего расширения типов
export type Id = ExtractId<typeof defaultStore>;
export interface State extends ExtractState<typeof defaultStore> {}
export interface Getters extends ExtractGetters<typeof defaultStore> {}
export interface Actions extends ExtractActions<typeof defaultStore> {}
// StoreRegistryKey легкий алиас для RegistryKey<Store<...>>
export const injectionKey = `store:${defaultStore.id}` as unknown as StoreRegistryKey<Id, State, Getters, Actions>;
export default useStoreWrapper<Id, State, Getters, Actions>(injectionKey, defaultStore);
// Идентично
const useStore = defineStore(defaultStore);
export default (registry?: Registry) =>
useRegistryItem(injectionKey, registry, ({ $pinia }, resolvedRegistry) => {
setActiveRegistry(resolvedRegistry);
return useStore($pinia);
});
Шаг 1.1 (Setup описание)
import {
type ExtractSetupState,
type ExtractSetupGetters,
type ExtractSetupActions,
type StoreRegistryKey,
useSetupStoreWrapper,
} from '@/modules/registry';
export const storeId = 'example';
export const defaultSetup = () => {
const foo = ref('foo');
const update = () => {
foo.value = 'bar';
};
return {
foo,
update,
};
};
export type Id = typeof storeId;
export interface State extends ExtractSetupState<ReturnType<typeof defaultSetup>> {}
export interface Getters extends ExtractSetupGetters<ReturnType<typeof defaultSetup>> {}
export interface Actions extends ExtractSetupActions<ReturnType<typeof defaultSetup>> {}
export const injectionKey = `store:${storeId}` as unknown as StoreRegistryKey<Id, State, Getters, Actions>;
export default useSetupStoreWrapper<Id, ReturnType<typeof defaultSetup>, State, Getters, Actions>(injectionKey, storeId, defaultSetup);
Шаг 2 (Реализация зависимости)
// registry/stores/example.ts
import { injectionKey, defaultStore } from '@/registry/stores/example';
import {
defineRegistryStore,
extendStore,
setActiveRegistry,
type ExtractState,
type ExtractGetters,
type ExtractActions,
} from '@/modules/registry';
// Расширение defaultStore
const extendedStore = extendStore(defaultStore, {
state: (prevState) => ({
...prevState,
baz: 'baz',
}),
getters: {
barBaz (state) {
return state.bar + state.baz;
},
},
actions: {
someActionInAnotherStore () {
const anotherStore = useAnotherRegistryStore(this.$registry);
},
},
});
// Шаблонный код для расширения типов
declare module 'shared-front/lib/registry/stores/example' {
interface State extends ExtractState<typeof extendedStore> {}
interface Getters extends ExtractGetters<typeof extendedStore> {}
interface Actions extends ExtractActions<typeof extendedStore> {}
}
export default defineRegistryStore(injectionKey, extendStore);
// Идентично
const useStore = defineStore(extendedStore);
export default defineRegistryItem(injectionKey, ({ $pinia }, registry) => {
setActiveRegistry(registry);
return useStore($pinia);
});
Шаг 2.1 (Setup реализация)
// registry/stores/example.ts
import { injectionKey, storeId, defaultSetup } from '@/registry/stores/example';
import {
defineRegistrySetupStore,
extendSetupStore,
type ExtractSetupState,
type ExtractSetupGetters,
type ExtractSetupActions,
} from '@/modules/registry';
const extendedSetup = extendSetupStore((exampleStore) => {
const uppercasedFoo = computed(() => {
return exampleStore.foo.value.toUpperCase()
});
return {
...exampleStore,
uppercasedFoo,
};
}, defaultSetup);
declare module 'shared-front/lib/registry/stores/example' {
interface State extends ExtractSetupState<ReturnType<typeof extendedSetup>> {}
interface Getters extends ExtractSetupGetters<ReturnType<typeof extendedSetup>> {}
interface Actions extends ExtractSetupActions<ReturnType<typeof extendedSetup>> {}
}
export default defineRegistrySetupStore(injectionKey, storeId, extendedSetup);
Не стоит заменять состояние из исходного стора, т.к. исходная setup функция может на него полагаться
Шаг 3 (Provide зависимости)
Без изменений
Шаг 4 (Использование зависимости)
В основном без изменений
Импорта другого pinia store реестра из текущего.
export default {
...
actions: {
async getExample() {
const exampleStore = useExampleStore();
await exampleStore.someAction();
// После первого await небходимо явно указывать реестр
const anotherStore = useAnotherStore(this.$registry);
},
},
...
}