SchemaInitializer
new SchemaInitializer(options)
1interface SchemaInitializerOptions<P1 = ButtonProps, P2 = {}> {
2 Component?: ComponentType<P1>;
3 componentProps?: P1;
4 style?: React.CSSProperties;
5 title?: string;
6 icon?: ReactNode;
7
8 items?: SchemaInitializerItemType[];
9 ItemsComponent?: ComponentType<P2>;
10 itemsComponentProps?: P2;
11 itemsComponentStyle?: React.CSSProperties;
12
13 insertPosition?: 'beforeBegin' | 'afterBegin' | 'beforeEnd' | 'afterEnd';
14 designable?: boolean;
15 wrap?: (s: ISchema) => ISchema;
16 onSuccess?: (data: any) => void;
17 insert?: InsertType;
18 useInsert?: () => InsertType;
19
20 popover?: boolean;
21 popoverProps?: PopoverProps;
22}
23
24class SchemaInitializer<P1 = ButtonProps, P2 = {}> {
25 constructor(options: SchemaInitializerOptions<P1, P2> & { name: string }): SchemaInitializer<P1, P2>;
26 add(name: string, item: Omit<SchemaInitializerItemType, 'name'>): void
27 get(nestedName: string): SchemaInitializerItemType | undefined
28 remove(nestedName: string): void
29}
详细解释
-
name:唯一标识,必填
-
Component 相关
- Component:触发组件,默认是
Button
组件
- componentProps: 组件属性,默认是
ButtonProps
- title: 按钮的文本
- icon:按钮的 icon 属性
- style:组件的样式
-
Items 相关
- items:列表项配置
- ItemsComponent:默认是渲染成一个列表的形式,可通过此参数自定义 items
- itemsComponentProps:
ItemsComponent
的属性
- itemsComponentStyle:
ItemsComponent
的样式
-
popover 组件相关
- popover:是否使用 popover,默认为
true
- popoverProps:popover 的属性
-
Schema 操作相关
示例
基础用法
1const myInitializer = new SchemaInitializer({
2 name: 'myInitializer',
3 title: 'Add Block',
4 // 插入位置
5 insertPosition: 'beforeEnd',
6 items: [
7 {
8 name: 'a',
9 title: 'Item A',
10 Component: Demo,
11 },
12 ],
13});
定制化Component
1const myInitializer = new SchemaInitializer({
2 name: 'myInitializer',
3 Component: (props) => (
4 <Avatar style={{ cursor: 'pointer' }} {...props}>
5 C
6 </Avatar>
7 ),
8 componentProps: {
9 size: 'large',
10 },
11 items: [
12 {
13 name: 'a',
14 title: 'Item A',
15 Component: Demo,
16 }
17 ],
18});
不使用 Popover
关于 useDesignable()
的说明请参考 useDesignable。
1const schema = {
2 type: 'void',
3 title: Math.random(),
4 'x-component': 'Hello',
5};
6const MyInitializerComponent = () => {
7 const { insertBeforeEnd } = useDesignable();
8 return <Button onClick={() => insertBeforeEnd(schema)}>Add block</Button>
9}
10
11const myInitializer = new SchemaInitializer({
12 name: 'myInitializer',
13 title: 'Add block',
14 popover: false,
15 Component: MyInitializerComponent,
16});
定制化 Items
1const CustomListGridMenu: FC<SchemaInitializerItemsProps<ButtonProps, ListProps<any>>> = (props) => {
2 const { items, options, ...others } = props;
3 return (
4 <List
5 {...others}
6 style={{ marginTop: 20 }}
7 dataSource={items}
8 grid={{ gutter: 16, column: 2 }}
9 renderItem={(item) => (
10 <List.Item style={{ minWidth: 100, textAlign: 'center' }}>
11 <SchemaInitializerChild {...item} />
12 </List.Item>
13 )}
14 ></List>
15 );
16};
17
18const myInitializer = new SchemaInitializer({
19 name: 'myInitializer',
20 title: 'Button Text',
21 ItemsComponent: CustomListGridMenu,
22 items: [
23 {
24 name: 'a',
25 title: 'Item A',
26 Component: Demo,
27 }
28 ],
29});
options.items 配置详解
类型
1interface SchemaInitializerComponentCommonProps {
2 title?: string;
3 schema?: ISchema;
4 style?: React.CSSProperties;
5 className?: string;
6}
7
8interface SchemaInitializerItemBaseType<T = {}> extends SchemaInitializerComponentCommonProps {
9 name: string;
10 sort?: number;
11 type?: string;
12 Component?: string | ComponentType<T>;
13 componentProps?: Omit<T, 'children'>;
14 useComponentProps?: () => Omit<T, 'children'>;
15 useVisible?: () => boolean;
16 children?: SchemaInitializerItemType[];
17 useChildren?: () => SchemaInitializerItemType[];
18 [index: string]: any;
19}
两种定义方式:Component
和type
1const Demo = () => {
2 // 最终渲染 `SchemaInitializerItem`
3 return <SchemaInitializerItem title='Demo' />
4}
5
6const myInitializer = new SchemaInitializer({
7 name: 'myInitializer',
8 items: [
9 {
10 name: 'a',
11 Component: Demo, // 通过 Component 定义
12 }
13 ],
14});
Tachybase 内置了一些常用的 type
,例如 type: 'item'
,相当于 Component: SchemaInitializerItem
。
更多内置类型,请参考:内置组件和类型
1const myInitializer = new SchemaInitializer({
2 name: 'myInitializer',
3 items: [
4 {
5 name: 'a',
6 type: 'item',
7 title: 'Demo'
8 }
9 ],
10});
children
和动态方式useChildren
对于某些组件而言是有子列表项的,例如 type: 'itemGroup'
,那么我们使用 children 属性,同时考虑到某些场景下 children 是动态的,需要从 Hooks 里面获取,那么就可以通过 useChildren
来定义。
动态显示隐藏useVisible
组件属性componentProps
和动态属性useComponentProps
对于一些通用组件,我们可以通过 componentProps
来定义组件属性,同时考虑到某些场景下组件属性是动态的,需要从 Hooks 里面获取,那么就可以通过 useComponentProps
来定义。
当然也可以不使用这两个属性,直接封装成一个组件,然后通过 Component
来定义。
公共属性和组件属性
1{
2 name: 'demo',
3 title: 'Demo',
4 foo: 'bar',
5 Component: Demo,
6 componentProps: {
7 zzz: 'xxx',
8 },
9}
从上面的示例中我么看到,从配置项中获取组件组件所需的数据有两个方式:
- 组件属性:通过
componentProps
来定义,例如 zzz: 'xxx'
- 公共属性:将属性直接定义在配置项上,例如
foo: 'bar'
、name
、title
在获取上
1const Demo = (props) => {
2 console.log(props); // { zzz: 'xxx' }
3 const { foo } = useSchemaInitializerItem(); // { foo: 'bar' }
4}
实例方法
1const myInitializer = new SchemaInitializer({
2 name: 'myInitializer',
3 title: 'Button Text',
4 items: [
5 {
6 name: 'a',
7 title: 'item a',
8 type: 'itemGroup',
9 children: [
10 {
11 name: 'a1',
12 title: 'item a1',
13 }
14 ],
15 },
16 ],
17});
1import { SchemaInitializer, Application, useSchemaInitializerRender } from '@tachybase/client';
2const myInitializer = new SchemaInitializer({
3 name: 'myInitializer',
4 title: 'Button Text',
5 items: [
6 {
7 name: 'a',
8 title: 'item a',
9 type: 'itemGroup',
10 children: [
11 {
12 name: 'a1',
13 title: 'item a1',
14 type: 'item',
15 }
16 ],
17 },
18 ],
19});
20
21const Root = () => {
22 const { render } = useSchemaInitializerRender('myInitializer');
23 return render();
24}
25const app = new Application({
26 schemaInitializers: [myInitializer],
27 providers: [Root],
28 designable: true,
29});
30
31export default app.getRootComponent();
schemaInitializer.add()
用于新增 Item,另一种添加方式参考 schemaInitializerManager.addItem();
1class SchemaInitializer {
2 add(name: string, item: Omit<SchemaInitializerItemType, 'name'>): void
3}
第一个参数是 name,作为唯一标识,用于增删改查,并且 name
支持 .
用于分割层级。
1myInitializer.add('b', {
2 type: 'item',
3 title: 'item b',
4})
5
6myInitializer.add('a.a2', {
7 type: 'item',
8 title: 'item a2',
9})
1import { SchemaInitializer, Application, useSchemaInitializerRender } from '@tachybase/client';
2const myInitializer = new SchemaInitializer({
3 name: 'myInitializer',
4 title: 'Button Text',
5 items: [
6 {
7 name: 'a',
8 title: 'item a',
9 type: 'itemGroup',
10 children: [
11 {
12 name: 'a1',
13 title: 'item a1',
14 type: 'item',
15 }
16 ],
17 },
18 ],
19});
20
21myInitializer.add('b', {
22 type: 'item',
23 title: 'item b',
24})
25
26myInitializer.add('a.a2', {
27 type: 'item',
28 title: 'item a2',
29})
30
31const Root = () => {
32 const { render } = useSchemaInitializerRender('myInitializer');
33 return render();
34}
35const app = new Application({
36 schemaInitializers: [myInitializer],
37 providers: [Root],
38 designable: true,
39});
40
41
42export default app.getRootComponent();
schemaInitializer.get()
1class SchemaInitializer {
2 get(nestedName: string): SchemaInitializerItemType | undefined
3}
1const itemA = myInitializer.get('a')
2
3const itemA1 = myInitializer.add('a.a1')
schemaInitializer.remove()
另一种移除方式参考 schemaInitializerManager.addItem();
1class SchemaInitializer {
2 remove(nestedName: string): void
3}
1myInitializer.remove('a.a1')
2
3myInitializer.remove('a')
Hooks
useSchemaInitializer()
用于获取 SchemaInitializer
上下文内容。
1export type InsertType = (s: ISchema) => void;
2
3const useSchemaInitializer: () => {
4 insert: InsertType;
5 options: SchemaInitializerOptions<any>;
6 visible?: boolean;
7 setVisible?: (v: boolean) => void;
8}
-
参数详解
insert
:参数是 Schema 对象,用于插入 Schema
options
:获取 new SchemaInitializer(options)
时 options 配置
visible
:popover 是否显示
setVisible
:设置 popover 显示状态
-
示例
1const schema = {
2 type: 'void',
3 'x-component': 'Hello',
4}
5const Demo = () => {
6 const { insert } = useSchemaInitializer();
7 const handleClick = () => {
8 insert(schema);
9 };
10 return <SchemaInitializerItem title={'Demo'} onClick={handleClick}></SchemaInitializerItem>;
11}
useSchemaInitializerRender()
用于渲染 SchemaInitializer
。
1function useSchemaInitializerRender(name: string, options?: SchemaInitializerOptions): {
2 exists: boolean;
3 render: (props?: SchemaInitializerOptions) => React.FunctionComponentElement;
4}
返回的 render
方法可以接收一个参数,用于覆盖 new SchemaInitializer(options)
的 options
配置。
1const Demo = () => {
2 const filedSchema = useFieldSchema();
3 const { render } = useSchemaInitializerRender(fieldSchema['x-initializer'], fieldSchema['x-initializer-props']);
4 return <div>
5 <div>{ render() }</div>
6 <div>可以进行参数的二次覆盖:{ render({ style: { color: 'red' } }) }</div>
7 </div>
8}
useSchemaInitializerItem()
用于获取配置项内容的,配置项是指的 SchemaInitializer
中的 items
中的一项。
1const useSchemaInitializerItem: <T = any>() => T
1const myInitializer = new SchemaInitializer({
2 name: 'myInitializer',
3 title: 'Button Text',
4 items: [
5 {
6 name: 'a',
7 title: 'Item A',
8 foo: 'bar',
9 Component: Demo,
10 },
11 ],
12});
13
14/**
15 * 通过 useSchemaInitializerItem() 获取到的是
16 * {
17 * name: 'a',
18 * title: 'Item A',
19 * foo: 'bar',
20 * Component: Demo,
21 * }
22 */
23const Demo = () => {
24 const { title, foo } = useSchemaInitializerItem();
25 return <div>{ title } - { foo }</div>
26}
内置组件和类型
type | Component | 效果 |
---|
item | SchemaInitializerItem | 文本 |
itemGroup | SchemaInitializerItemGroup | 分组,同 antd Menu 组件的 type: 'group' |
subMenu | SchemaInitializerSubMenu | 子菜单,同 antd Menu 组件的子菜单 |
divider | SchemaInitializerDivider | 分割线,同 antd Menu 组件的 type: 'divider' |
switch | SchemaInitializerSwitch | 开关 |
actionModal | SchemaInitializerActionModal | 弹窗 |
以下每个示例都提供了 2 种定义方式,一种是通过 Component
定义,另一种是通过 type
定义。
type: 'item'
&SchemaInitializerItem
文本项。
1interface SchemaInitializerItemProps {
2 style?: React.CSSProperties;
3 className?: string;
4 name?: string;
5 icon?: React.ReactNode;
6 title?: React.ReactNode;
7 items?: SchemaInitializerItemType[];
8 onClick?: (args?: any) => any;
9}
核心参数是 title
、icon
、onClick
、items
,其中 onClick
用于插入 Schema,items
用于渲染子列表项。
type: 'itemGroup'
& SchemaInitializerItemGroup
分组。
1interface SchemaInitializerItemGroupProps {
2 name: string;
3 title: string;
4 children?: SchemaInitializerOptions['items'];
5 divider?: boolean;
6}
核心参数是 title
、children
,其中 children
用于渲染子列表项,divider
用于渲染分割线。
type: 'switch'
& SchemaInitializerSwitch
Switch 切换按钮。
1interface SchemaInitializerSwitchItemProps extends SchemaInitializerItemProps {
2 checked?: boolean;
3 disabled?: boolean;
4}
核心参数是 checked
、onClick
,其中 onClick
用于插入或者移除 Schema。
type: 'subMenu'
& SchemaInitializerSubMenu
子菜单。
type: 'divider'
& SchemaInitializerDivider
分割线。
type: 'actionModal'
& SchemaInitializerActionModal
Component Mode
Item Mode
SchemaInitializerActionModal
需要加上 isItem
属性
渲染组件
SchemaInitializerChildren
用于自定义渲染多个列表项。
1const Demo = ({ children }) => {
2 // children: [{ name: 'a1', Component: ItemA1 }, { name: 'a2', type: 'item', title: 'ItemA2' }]
3 return <SchemaInitializerChildren>{ children }</SchemaInitializerChildren>
4}
5
6const myInitializer = new SchemaInitializer({
7 name: 'myInitializer',
8 title: 'Button Text',
9 items: [
10 {
11 name: 'test',
12 Component: Demo,
13 children: [
14 {
15 name: 'a1',
16 Component: ItemA1,
17 },
18 {
19 name: 'a2',
20 type: 'item',
21 title: 'ItemA2',
22 }
23 ]
24 }
25 ],
26});
SchemaInitializerChild
用于自定义渲染单个列表项。
1const Demo = (props) => {
2 return <SchemaInitializerChild {...props}/>
3}