插件类型
插件可以简单分为UI展示插件与行为插件,通过插件可以方便扩展配置规则,同时「基于宿主配置组件」的上下文(后面简称ctx),插件可以承载更加强大与灵活的能力。
所有插件都有如下形态
{
plugin: 'someone', // 可以理解为下面没有额外属性的简写
// 或者
plugin: {
type: 'someone', // 插件名称
prop1: 'foo',
prop2: 'boo'
}
// 或者
plugin: (ctx) => {
// ...someone logic
}
}
插件场景
插件支持三种类型(还有dependency、convertParams、converter插件会单独一part列出):
- 渲染插件
- 行为插件
- 表单插件
1. 渲染插件(render)
场景:
- 表格渲染单元icon、tag、badge等
- 表格操作按钮等
- 表单操作按钮等
除了config,渲染插件可以通过ctx来改变组件属性。
2. 行为插件(action)
场景:
- 生命周期(组件初始化等)
- 与渲染插件结合,由渲染插件事件触发
常见行为如请求、路由跳转、弹窗等,行为插件基于ctx可以将行为反馈结果施加到宿主配置组件。
3. 表单插件(field)
场景:
与Form配置组件结合使用,antd数据录入组件及符合antd表单自定义组件规范的都可以转化为表单插件。
插件规范
export type PluginType = 'render' | 'field' | 'action';
以下RenderPlugin、FieldPlugin、ActionPlugin对应了三种插件的配置规则。
1. 渲染插件
// 渲染插件
export type RenderPluginFunction = (ctx: Ctx) => React.ReactElement;
// 渲染插件配置规则
export type RenderPlugin = {
type: string | RenderPluginFunction;
props: Record<string, any>;
functionProps: Record<string, (ctx: Ctx) => string>;
};
示例
const ctx = {name: 'sula'}
// 配置
const config = {
type: 'tag',
props: {
children: 'i am ${name}'
},
functionProps: {
closable: (ctx) => ctx.name === 'sula'
}
}
// 结果为
<Tag closable>i am sula</Tag>
2. 行为插件
// 行为插件
export type ActionPluginFunction = (ctx: Ctx) => Promise<any> | any | void;
export type ActionBeforeFunction = (ctx: Ctx) => Promise<boolean> | boolean | void;
export type ActionHookFunction = (ctx: Ctx) => void;
// 行为插件配置规则
export type ActionPlugin = {
type: string | ActionPluginFunction;
before?: ActionBeforeFunction;
error?: ActionHookFunction;
final?: ActionHookFunction;
finish?: ActionPlugin | ActionPlugin[];
[key: string]: any;
};
示例
const ctx = {
table: {
refresh: () => {},
}
}
// 配置
const config = {
render: {
type: 'button',
props: {
children: 'submit'
},
action: (ctx) => { // 可以变成一个插件例如refreshTable
ctx.table.refresh();
}
},
}
// 结果为
<Button onClick={() => {
ctx.table.refresh();
}}>submit</Button>
3. 表单插件
表单插件与渲染插件格式上是类似的,只是ctx与场景上的不同。
// 表单插件配置规则
export type FieldPlugin = RenderPlugin;
示例
const ctx = {mode: 'view'}
// 配置
const config = {
type: 'input',
props: {
placeholder: '@{mode} mode'
},
functionProps: {
disabled: (ctx) => ctx.name === 'view'
}
}
// 结果为
<Input placeholder="view mode" disabled />
插件注册
插件是为了将重复逻辑更加复用,因此直接写方法可以理解为是插件的“内联”形式。
// 注册渲染插件
sula.renderType('tag', (ctx, config) => {
return <Tag {...config.props} />;
});
render: {
type: 'tag',
props: {
type: 'primary'
}
}
// 内联写法
render: (ctx) => {
return <Tag type="primary" />;
}