SchemaComponent

Context

SchemaComponentContext

1interface SchemaComponentContext {
2  scope?: any;
3  components?: SchemaReactComponents;
4  refresh?: () => void;
5  reset?: () => void;
6  designable?: boolean;
7  setDesignable?: (value: boolean) => void;
8}

Schema 渲染的上下文。

  • scope:Schema 中变量的映射
  • components: Schema 中组件的映射
  • refresh:触发 React 重新渲染的工具函数
  • reset:重置整个 Schema 节点
  • designable:是否显示设计器,默认 false
  • setDesignable:用于切换 designable 的值

Hooks

useSchemaOptionsContext()

用于获取注册的 scopecomponents

1const { scope, components } = useSchemaOptionsContext();

组件

SchemaComponentProvider

其是对 SchemaComponentContext.ProviderFormProvider 的封装,并内置在 Application 中,并且会将 app.componentsapp.scopes 传递过去,所以一般情况下 不需要关注 此组件。

  • props
1interface SchemaComponentProviderProps {
2  designable?: boolean;
3  form?: Form;
4  scope?: any;
5  components?: SchemaReactComponents;
6}
  • 详细解释
    • designableSchemaComponentContextdesignable 的默认值
    • form:Tachybase 的 Schema 能力是基于 formily 的 FormProvider 提供的,form 是其参数,默认为 createForm()
    • scope:Schema 中所用到的变量,会通过 SchemaComponentContext 进行传递
    • components:Schema 中所用到的组件,会通过 SchemaComponentContext 进行传递

SchemaComponent

用于渲染 Schema,此组件必须和 SchemaComponentProvider 一起使用,因为 SchemaComponentProvider 提供了 FormProvider 作为渲染 Schema 的根节点。

  • Props
1type SchemaComponentProps = (ISchemaFieldProps | IRecursionFieldProps) & {
2    memoized?: boolean;
3    components?: SchemaReactComponents;
4    scope?: any;
5}
  • 详细解释

    • memoized:当为 true 时,会对每层的 Schema 使用 useMemo() 进行处理
    • components:同 SchemaComponentProvidercomponents
    • scope: 同 SchemaComponentProvidercomponents

综合示例

结合 SchemaComponentProvideruseSchemaComponentContext()SchemaComponent

1/**
2 * defaultShowCode: true
3 */
4import { SchemaComponentProvider, useSchemaComponentContext, SchemaComponent, } from '@tachybase/client';
5const Hello = () => {
6    const { designable, setDesignable } = useSchemaComponentContext();
7    return <div>
8        <div style={{ padding: 20, border: designable ? '1px solid red' : undefined }} contentEditable={designable}>hello world</div>
9        <button onClick={() => setDesignable(!designable) }>change designable</button>
10    </div>;
11}
12
13const schema = {
14  type: 'void',
15  name: 'hello',
16  'x-component': 'Hello',
17}
18
19const Demo = () => {
20  return <SchemaComponent schema={schema} />
21}
22
23const Root = () => {
24  return <SchemaComponentProvider components={{ Hello }}>
25    <Demo />
26  </SchemaComponentProvider>
27}
28
29export default Root;

使用 new Application() 的方式,其内置了 SchemaComponentProvider ,我们可以如下操作:

1/**
2 * defaultShowCode: true
3 */
4import { Application, Plugin, useSchemaComponentContext, SchemaComponent } from '@tachybase/client';
5const Hello = () => {
6    const { designable, setDesignable } = useSchemaComponentContext();
7    return <div>
8        <div style={{ padding: 20, border: designable ? '1px solid red' : undefined }} contentEditable={designable}>hello world</div>
9        <button onClick={() => setDesignable(!designable) }>change designable</button>
10    </div>;
11}
12
13const schema = {
14    type: 'void',
15    name: 'hello',
16    'x-component': 'Hello',
17}
18
19const HomePage = () => {
20    return <SchemaComponent components={{ Hello }} schema={schema} />
21}
22
23class MyPlugin extends Plugin {
24    async load() {
25        this.app.addComponents({ Hello });
26        this.app.router.add('home', {
27            path: '/',
28            Component: HomePage,
29        })
30    }
31}
32
33const app = new Application({
34    router: {
35        type: 'memory',
36        initialEntries: ['/'],
37    },
38    plugins: [MyPlugin],
39})
40
41export default app.getRootComponent();

SchemaComponentOptions

在应用中,会有很多层级的嵌套,每一层都可能提供自己的组件和 scope,此组件就是为了层层传递 Schema 所需的 componentsscope 的。

  • props
1interface SchemaComponentOptionsProps {
2  scope?: any;
3  components?: SchemaReactComponents;
4}
  • 示例
1/**
2 * defaultShowCode: true
3 */
4import { SchemaComponentProvider, useSchemaComponentContext, SchemaComponent, SchemaComponentOptions } from '@tachybase/client';
5const World = () => {
6   return <div>world</div>
7}
8
9const Hello = ({ children }) => {
10    return <div>
11        <div>hello</div>
12        <SchemaComponentOptions components={{ World }}>{ children }</SchemaComponentOptions>
13    </div>;
14}
15
16const schema = {
17    type: 'void',
18    name: 'hello',
19    'x-component': 'Hello',
20    properties: {
21        world: {
22          type: 'void',
23          'x-component': 'World',
24        },
25    },
26}
27
28const Root = () => {
29    return <SchemaComponentProvider components={{ Hello }}>
30       <SchemaComponent schema={schema} />
31    </SchemaComponentProvider>
32}
33
34export default Root;