sula icon indicating copy to clipboard operation
sula copied to clipboard

RFC - 插件规范

Open xz8la8 opened this issue 5 years ago • 2 comments

插件类型

插件可以简单分为UI展示插件行为插件,通过插件可以方便扩展配置规则,同时「基于宿主配置组件」的上下文(后面简称ctx),插件可以承载更加强大与灵活的能力。

所有插件都有如下形态

{
   plugin: 'someone', // 可以理解为下面没有额外属性的简写
   // 或者
   plugin: {
     type: 'someone', // 插件名称
     prop1: 'foo',
     prop2: 'boo'
   }
  // 或者
  plugin: (ctx) => {
     // ...someone logic
  }
}

插件场景

插件支持三种类型(还有dependency、convertParams、converter插件会单独一part列出):

  1. 渲染插件
  2. 行为插件
  3. 表单插件

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" />;
}

xz8la8 avatar Apr 18 '20 06:04 xz8la8

比如 render 类型的插件,注册完后如何渲染出来?

sorrycc avatar Apr 20 '20 08:04 sorrycc

比如 render 类型的插件,注册完后如何渲染出来?

https://rfc.sula.now.sh/#/sula-core/rfc ,这里有个例子

xz8la8 avatar Apr 20 '20 08:04 xz8la8