ruoyi-plus-soybean/packages/hooks/src/use-context.ts

97 lines
2.1 KiB
TypeScript
Raw Normal View History

2023-11-17 08:45:00 +08:00
import { inject, provide } from 'vue';
import type { InjectionKey } from 'vue';
/**
2023-12-14 21:45:29 +08:00
* Use context
*
2023-11-17 08:45:00 +08:00
* @example
2023-12-14 21:45:29 +08:00
* ```ts
* // there are three vue files: A.vue, B.vue, C.vue, and A.vue is the parent component of B.vue and C.vue
2023-11-17 08:45:00 +08:00
*
2023-12-14 21:45:29 +08:00
* // context.ts
* import { ref } from 'vue';
* import { useContext } from '@sa/hooks';
2023-11-17 08:45:00 +08:00
*
2023-12-14 21:45:29 +08:00
* export const { setupStore, useStore } = useContext('demo', () => {
* const count = ref(0);
2023-11-17 08:45:00 +08:00
*
2023-12-14 21:45:29 +08:00
* function increment() {
* count.value++;
* }
2023-11-17 08:45:00 +08:00
*
2023-12-14 21:45:29 +08:00
* function decrement() {
* count.value--;
* }
2023-11-17 08:45:00 +08:00
*
2023-12-14 21:45:29 +08:00
* return {
* count,
* increment,
* decrement
* };
* })
* ``` // A.vue
* ```vue
* <template>
* <div>A</div>
* </template>
* <script setup lang="ts">
* import { setupStore } from './context';
2023-11-17 08:45:00 +08:00
*
2023-12-14 21:45:29 +08:00
* setupStore();
* // const { increment } = setupStore(); // also can control the store in the parent component
* </script>
* ``` // B.vue
* ```vue
* <template>
* <div>B</div>
* </template>
* <script setup lang="ts">
* import { useStore } from './context';
2023-11-17 08:45:00 +08:00
*
2023-12-14 21:45:29 +08:00
* const { count, increment } = useStore();
* </script>
* ```;
2023-11-17 08:45:00 +08:00
*
2023-12-14 21:45:29 +08:00
* // C.vue is same as B.vue
2023-11-17 08:45:00 +08:00
*
2023-12-14 21:45:29 +08:00
* @param contextName Context name
* @param fn Context function
2023-11-17 08:45:00 +08:00
*/
export default function useContext<T extends (...args: any[]) => any>(contextName: string, fn: T) {
type Context = ReturnType<T>;
const { useProvide, useInject: useStore } = createContext<Context>(contextName);
function setupStore(...args: Parameters<T>) {
const context: Context = fn(...args);
return useProvide(context);
}
return {
2023-12-14 21:45:29 +08:00
/** Setup store in the parent component */
2023-11-17 08:45:00 +08:00
setupStore,
2023-12-14 21:45:29 +08:00
/** Use store in the child component */
2023-11-17 08:45:00 +08:00
useStore
};
}
2023-12-14 21:45:29 +08:00
/** Create context */
2023-11-17 08:45:00 +08:00
function createContext<T>(contextName: string) {
const injectKey: InjectionKey<T> = Symbol(contextName);
function useProvide(context: T) {
provide(injectKey, context);
return context;
}
function useInject() {
return inject(injectKey) as T;
}
return {
useProvide,
useInject
};
}