前端:抽象了创建服务上下文

This commit is contained in:
lsy 2024-11-14 23:01:21 +08:00
parent 1385251318
commit 88bf3b5592
7 changed files with 60 additions and 131 deletions

View File

@ -8,8 +8,8 @@
*/ */
import { SerializeType } from "./generalRequirement"; import { SerializeType } from "./generalRequirement";
import { ExtensionProps } from "types/extensionRequirement"; import { ExtensionProps } from "types/extensionRequirement";
import { useExtention } from "hooks/extensionService";
import { ExtensionService } from "service/extensionService"; import { ExtensionService } from "service/extensionService";
import { useExtension } from "hooks/servicesProvider";
export interface PluginConfig { export interface PluginConfig {
name: string; // 插件名称 name: string; // 插件名称
@ -46,25 +46,14 @@ export interface PluginConfiguration {
}; };
} }
export interface PluginDependencies {
plugins: string[]; // 依赖的插件列表(可选)
themes: string[]; // 依赖的主题列表(可选)
}
/** /**
* *
* *
* *
*/ */
export class usePluginProps implements ExtensionProps { export class usePluginProps extends ExtensionProps {
private extensionService: ExtensionService = useExtention();
private dependencies: PluginDependencies;
constructor(dependencies: PluginDependencies) {
this.dependencies = dependencies;
}
action?: ((...args: any[]) => void); // 动作函数(可选)
component?: (...args: any[]) => React.FC; // 组件函数(可选)
text?: (...args: any[]) => string; // 文本生成函数(可选)
} }

View File

@ -1,8 +1,8 @@
import { Meta, Outlet, Scripts, ScrollRestoration } from "@remix-run/react"; import { Meta, Outlet, Scripts, ScrollRestoration } from "@remix-run/react";
import type { LoaderFunction } from "@remix-run/node"; import type { LoaderFunction } from "@remix-run/node";
import { useLoaderData } from "@remix-run/react"; import { useLoaderData } from "@remix-run/react";
import { ThemeProvider } from "hooks/themeContext";
import { createContext, useContext, ReactNode } from 'react'; import { createContext, useContext, ReactNode } from 'react';
import { ServiceProvider } from "hooks/servicesProvider";
import "./tailwind.css"; import "./tailwind.css";
export function Layout({ children }: { children: React.ReactNode }) { export function Layout({ children }: { children: React.ReactNode }) {
@ -17,9 +17,9 @@ export function Layout({ children }: { children: React.ReactNode }) {
<Meta /> <Meta />
</head> </head>
<body> <body>
<ThemeProvider> <ServiceProvider>
{children} {children}
</ThemeProvider> </ServiceProvider>
<ScrollRestoration /> <ScrollRestoration />
<Scripts /> <Scripts />
</body> </body>

View File

@ -1,55 +1,50 @@
// File path: /hooks/createServiceContext.tsx // File path: /hooks/createServiceContext.tsx
import { createContext, ReactNode, useContext } from "react"; import { createContext, useContext, ReactNode, FC } from 'react';
/** /**
* 使 *
*
* @param name -
* @param getInstance -
* @returns Provider useService
*/ */
interface ServiceContextResult<T> { type ServiceContextReturn<N extends string,T> = {
Provider: React.FC<{ children: ReactNode }>; // 提供服务实例的组件 [K in `${N}Provider`]: FC<{ children: ReactNode }>;
useService: () => T; // 获取服务实例的钩子 } & {
} [K in `use${N}`]: () => T;
};
/** /**
* *
* *
* @param name - * @param serviceName -
* @param getInstance - * @param ServiceClass - getInstance
* @returns Provider useService
*/ */
export function createServiceContext<T>( export function createServiceContext<T, N extends string>(
name: string, serviceName: N,
getInstance: () => T getServiceInstance: () => T
): ServiceContextResult<T> { ): ServiceContextReturn<N,T> {
// 创建一个上下文,初始值为 undefined。
const ServiceContext = createContext<T | undefined>(undefined); const ServiceContext = createContext<T | undefined>(undefined);
// Provider 组件,用于提供服务实例给子组件 /**
const Provider = ({ children }: { children: ReactNode }) => { *
const service = getInstance(); */
const Provider: FC<{ children: ReactNode }> = ({ children }) => (
<ServiceContext.Provider value={getServiceInstance()}>
{children}
</ServiceContext.Provider>
);
return ( /**
<ServiceContext.Provider value={service}> *
{children} */
</ServiceContext.Provider>
);
};
// 获取服务实例的钩子
const useService = (): T => { const useService = (): T => {
const context = useContext(ServiceContext); const context = useContext(ServiceContext);
if (context === undefined) { if (context === undefined) {
throw new Error(`use${name} must be used within a ${name}Provider`); throw new Error(`use${serviceName} must be used within a ${serviceName}Provider`);
} }
return context; return context;
}; };
return { return {
Provider, [`${serviceName}Provider`]: Provider,
useService, [`use${serviceName}`]: useService,
}; } as ServiceContextReturn<N,T>;
} }

View File

@ -1,41 +0,0 @@
// File path: /d:/data/echoes/frontend/hooks/extensionService.tsx
/**
* Hook
*
* 访 Hook
*/
import { createContext, useContext, ReactNode } from 'react';
import { ExtensionService } from 'service/extensionService';
// 创建扩展服务上下文
const ExtensionContext = createContext<ExtensionService | undefined>(undefined);
/**
*
*
* @param children -
*/
export function ExtensionProvider({ children }: { children: ReactNode }) {
const extensionService = ExtensionService.getInstance(); // 获取扩展服务实例
return (
<ExtensionContext.Provider value={extensionService}>
{children}
</ExtensionContext.Provider>
)
}
/**
* Hook访
*
* @returns {ExtensionService} -
* @throws {Error} - ExtensionProvider
*/
export function useExtention(): ExtensionService {
const context = useContext(ExtensionContext); // 获取扩展服务上下文
if (context === undefined) {
throw new Error('useTheme must be used within a ThemeProvider'); // 抛出错误
}
return context; // 返回扩展服务实例
}

View File

@ -0,0 +1,22 @@
import { ExtensionService } from 'service/extensionService';
import { ThemeService } from 'service/themeService';
import { createServiceContext } from './createServiceContext';
import { ReactNode } from 'react';
export const {
ExtensionProvider,
useExtension
} = createServiceContext('Extension', () => ExtensionService.getInstance());
export const {
ThemeProvider,
useTheme
} = createServiceContext("Theme", () => ThemeService.getInstance());
export const ServiceProvider = ({ children }: { children: ReactNode })=>(
<ExtensionProvider>
<ThemeProvider>
{children}
</ThemeProvider>
</ExtensionProvider>
);

View File

@ -1,36 +0,0 @@
// File path: /hooks/themeContext.tsx
import { createContext, useContext, ReactNode } from 'react';
import { ThemeService } from 'service/themeService';
const ThemeContext = createContext<ThemeService | undefined>(undefined);
/**
* ThemeProvider
* 使 ThemeService
*
* @param children -
*/
export function ThemeProvider({ children }: { children: ReactNode }) {
const themeService = ThemeService.getInstance();
return (
<ThemeContext.Provider value={themeService}>
{children}
</ThemeContext.Provider>
);
}
/**
* useTheme 访
*
* @returns ThemeService -
* @throws Error - ThemeProvider 使
*/
export function useTheme(): ThemeService {
const context = useContext(ThemeContext);
if (context === undefined) {
throw new Error('useTheme must be used within a ThemeProvider');
}
return context;
}

View File

@ -88,7 +88,7 @@ export class ExtensionService {
} }
//获取指定配置文件 //获取指定配置文件
getConfiguration(pluginName: string): PluginConfiguration | undefined { private getConfiguration(pluginName: string): PluginConfiguration | undefined {
return this.configuration.get(pluginName); return this.configuration.get(pluginName);
} }
} }