refactor(client): improve schema component

This commit is contained in:
chenos 2022-01-25 00:18:34 +08:00
parent 6ba2d6b5e5
commit 3c54393073
11 changed files with 83 additions and 63 deletions

View File

@ -49,9 +49,9 @@ export const Form: ComposedForm = observer((props) => {
return decorator ? ( return decorator ? (
<FormDecorator form={form} /> <FormDecorator form={form} />
) : ( ) : (
<FormProvider form={form}> <FormContext.Provider value={form}>
<SchemaComponent schema={fieldSchema} /> <SchemaComponent schema={fieldSchema} />
</FormProvider> </FormContext.Provider>
); );
}); });

View File

@ -27,6 +27,7 @@ export const Menu: ComposedMenu = observer((props) => {
onSelect, onSelect,
mode, mode,
defaultSelectedUid, defaultSelectedUid,
sideMenuRefScopeKey,
defaultSelectedKeys: dSelectedKeys, defaultSelectedKeys: dSelectedKeys,
defaultOpenKeys: dOpenKeys, defaultOpenKeys: dOpenKeys,
...others ...others

View File

@ -1,20 +0,0 @@
import { RecursionField, SchemaExpressionScopeContext, SchemaOptionsContext } from '@formily/react';
import React, { useContext } from 'react';
import { SchemaComponentContext } from '../context';
import { IRecursionComponentProps } from '../types';
export const RecursionComponent: React.FC<IRecursionComponentProps> = (props) => {
const { components, scope } = useContext(SchemaComponentContext);
return (
<SchemaOptionsContext.Provider
value={{
scope: { ...scope, ...props.scope },
components: { ...components, ...props.components },
}}
>
<SchemaExpressionScopeContext.Provider value={{ ...scope, ...props.scope }}>
<RecursionField {...props} />
</SchemaExpressionScopeContext.Provider>
</SchemaOptionsContext.Provider>
);
};

View File

@ -42,5 +42,5 @@ const RequestSchemaComponent: React.FC<RemoteSchemaComponentProps> = (props) =>
}; };
export const RemoteSchemaComponent: React.FC<RemoteSchemaComponentProps> = (props) => { export const RemoteSchemaComponent: React.FC<RemoteSchemaComponentProps> = (props) => {
return props.uid ? <RequestSchemaComponent {...props}/> : null; return props.uid ? <RequestSchemaComponent {...props} /> : null;
}; };

View File

@ -1,6 +1,7 @@
import { ISchemaFieldProps, Schema } from '@formily/react'; import { ISchemaFieldProps, RecursionField, Schema } from '@formily/react';
import React, { useContext, useMemo } from 'react'; import React, { useContext, useMemo } from 'react';
import { SchemaComponentContext } from '../context'; import { SchemaComponentContext } from '../context';
import { SchemaComponentOptions } from './SchemaComponentOptions';
function toSchema(schema?: any) { function toSchema(schema?: any) {
if (Schema.isSchemaInstance(schema)) { if (Schema.isSchemaInstance(schema)) {
@ -18,8 +19,12 @@ function toSchema(schema?: any) {
} }
export function SchemaComponent(props: ISchemaFieldProps) { export function SchemaComponent(props: ISchemaFieldProps) {
const { schema, ...others } = props; const { components, scope, schema, ...others } = props;
const { SchemaField } = useContext(SchemaComponentContext);
const s = useMemo(() => toSchema(schema), []); const s = useMemo(() => toSchema(schema), []);
return <SchemaField {...others} schema={s} />; console.log('SchemaComponent', { components, scope });
return (
<SchemaComponentOptions inherit components={components} scope={scope}>
<RecursionField {...others} schema={s} />
</SchemaComponentOptions>
);
} }

View File

@ -0,0 +1,16 @@
import { SchemaExpressionScopeContext, SchemaOptionsContext } from '@formily/react';
import React, { useContext } from 'react';
import { ISchemaComponentOptionsProps } from '../types';
export const SchemaComponentOptions: React.FC<ISchemaComponentOptionsProps> = (props) => {
const { inherit } = props;
let options = useContext(SchemaOptionsContext);
const expressionScope = useContext(SchemaExpressionScopeContext);
const scope = { ...options?.scope, ...expressionScope, ...props.scope };
const components = { ...options?.components, ...props.components };
return (
<SchemaOptionsContext.Provider value={{ scope, components }}>
<SchemaExpressionScopeContext.Provider value={scope}>{props.children}</SchemaExpressionScopeContext.Provider>
</SchemaOptionsContext.Provider>
);
};

View File

@ -3,9 +3,10 @@ import { uid } from '@formily/shared';
import { createForm } from '@formily/core'; import { createForm } from '@formily/core';
import { useCookieState } from 'ahooks'; import { useCookieState } from 'ahooks';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { FormProvider, createSchemaField } from '@formily/react'; import { FormProvider } from '@formily/react';
import { ISchemaComponentProvider } from '../types'; import { ISchemaComponentProvider } from '../types';
import { SchemaComponentContext } from '../context'; import { SchemaComponentContext } from '../context';
import { SchemaComponentOptions } from './SchemaComponentOptions';
export const SchemaComponentProvider: React.FC<ISchemaComponentProvider> = (props) => { export const SchemaComponentProvider: React.FC<ISchemaComponentProvider> = (props) => {
const { components, children } = props; const { components, children } = props;
@ -14,21 +15,12 @@ export const SchemaComponentProvider: React.FC<ISchemaComponentProvider> = (prop
const form = props.form || useMemo(() => createForm(), [formId]); const form = props.form || useMemo(() => createForm(), [formId]);
const { t } = useTranslation(); const { t } = useTranslation();
const scope = { ...props.scope, t }; const scope = { ...props.scope, t };
const SchemaField = useMemo(
() =>
createSchemaField({
scope,
components,
}),
[],
);
const [active, setActive] = useCookieState('useCookieDesignable'); const [active, setActive] = useCookieState('useCookieDesignable');
return ( return (
<SchemaComponentContext.Provider <SchemaComponentContext.Provider
value={{ value={{
SchemaField,
components,
scope, scope,
components,
reset: () => setFormId(uid()), reset: () => setFormId(uid()),
refresh: () => setUid(uid()), refresh: () => setUid(uid()),
designable: active === 'true', designable: active === 'true',
@ -37,7 +29,11 @@ export const SchemaComponentProvider: React.FC<ISchemaComponentProvider> = (prop
}, },
}} }}
> >
<FormProvider form={form}>{children}</FormProvider> <FormProvider form={form}>
<SchemaComponentOptions inherit scope={scope} components={components}>
{children}
</SchemaComponentOptions>
</FormProvider>
</SchemaComponentContext.Provider> </SchemaComponentContext.Provider>
); );
}; };

View File

@ -1,17 +0,0 @@
import React, { useContext } from 'react';
import { SchemaOptionsContext, SchemaExpressionScopeContext } from '@formily/react';
import { SchemaComponentContext } from '../context';
export const SchemaOptionsExpressionScopeProvider: React.FC = (props) => {
const { components, scope } = useContext(SchemaComponentContext);
return (
<SchemaOptionsContext.Provider
value={{
scope,
components,
}}
>
<SchemaExpressionScopeContext.Provider value={{ scope }}>{props.children}</SchemaExpressionScopeContext.Provider>
</SchemaOptionsContext.Provider>
);
};

View File

@ -1,6 +1,5 @@
export * from './RecursionComponent';
export * from './SchemaComponent';
export * from './SchemaComponentProvider';
export * from './SchemaOptionsExpressionScopeProvider';
export * from './RemoteSchemaComponent';
export * from './DesignableSwitch'; export * from './DesignableSwitch';
export * from './RemoteSchemaComponent';
export * from './SchemaComponent';
export * from './SchemaComponentOptions';
export * from './SchemaComponentProvider';

View File

@ -11,9 +11,43 @@ group:
### SchemaComponentProvider ### SchemaComponentProvider
### SchemaComponent ```tsx | pure
<SchemaComponentProvider>
<SchemaComponent schema={{}}/>
</SchemaComponentProvider>
```
### RecursionComponent ### SchemaComponentOptions
提供 SchemaComponent 所需的 scope 和 components可以嵌套`inherit={true}` 时,继承父级的 scope 和 components。
```tsx | pure
<SchemaComponentOptions scope={{}} components={{}}>
</SchemaComponentOptions>
<SchemaComponentOptions scope={{}} components={{}}>
{/* 继承父级的 scope 和 components */}
<SchemaComponentOptions inherit scope={{}} components={{}}>
</SchemaComponentOptions>
</SchemaComponentOptions>
```
例如将 useTranslation 的 t 附加给 scope
```tsx | pure
import { useTranslation } from 'react-i18next';
function TranslationProvider(props) {
const { t } = useTranslation();
return (
<SchemaComponentOptions inherit scope={{ t }}>
{ props.children }
</SchemaComponentOptions>
);
}
```
### SchemaComponent
## Hooks ## Hooks

View File

@ -35,3 +35,9 @@ export interface IRecursionComponentProps extends IRecursionFieldProps {
scope?: any; scope?: any;
components?: SchemaReactComponents; components?: SchemaReactComponents;
} }
export interface ISchemaComponentOptionsProps {
scope?: any;
components?: SchemaReactComponents;
inherit?: boolean;
}