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