🪂 Pro Enum
ProEnum 是为了解决常见的 枚举/Select/Checkbox.Group/Radio.Group 甚至Suggestion/Cascader 的异步数据源的解决方案
设计思路
Formily 模型中的 enum 字段能够满足本地的枚举词典的需求, 但远程的其实更常用一些; 基于这个事实,使用归纳演绎法, 可以发现,上面提到的几个组件,所用到的数据源, 可以归纳为下面这种格式;
type Value = string | number;
export type ProEnumItem = {
label: string;
value: Value;
disabled?: boolean;
/** tree like */
isLeaf?: boolean;
children?: ProEnumItem[];
/** lazy */
loading?: boolean;
/** read pretty */
color?: keyof typeof BUILTIN_COLOR | (string & {});
};
因此, 设计了一个专用的 ProEnum 组件, 来增强原有的 enum 属性的表现力,当然, 这需要我们使用 useProEnumEffects 使用 FieldEffects 对 Field 改进劫持。
针对 Select/Radio.Group/Checkbox.Group
来讲, 劫持动作包含两部分
-
enum 属性支持 ProEnum 实例, 而这, 是一个支持远程加载的枚举, 并在组件 init 钩子中进行自动加并注入的 field.dataSource 属性, 也就是 enum 原来对应的属性值
-
劫持 readPretty 形态下的 field.componentType, 优化枚举值的展示
针对 Suggestion/Cascader 这种
代码案例
如此,我们就可以通过固定的形式, 方便的在 Formliy 中使用异步的枚举值, 以及轻松的适配 Suggestion(Select)/CascaderPlus
API
ProEnum
pretty 劫持属性
/**
* Schema 上的配置
* @example
* {
* type: 'string',
* enum: ProEnum.from([]),
* "x-component-props": {
* enum: {
* hijack: false,
* }
* }
* }
*/
type ProEnumSchemaOption = Pick<ProEnumOption, "mapToProp"> & {
pretty?: boolean;
showType?: React.ComponentProps<typeof ProEnumPretty>["showType"];
strict?: React.ComponentProps<typeof ProEnumPretty>["strictMode"];
// 额外的请求参数
params?: any;
};
/** 创建时候的配置 */
type ProEnumOption = {
mapToProp?: string;
cache?: boolean;
// > 0 启用
debounce?: number;
lazyTree?: boolean;
colorful?: boolean;
// 是否劫持 read pretty
pretty?: boolean;
};
type TItemsOrLoader =
| ProEnumItem[]
| ((params?: any) => Promise<ProEnumItem[]>);
export class ProEnum {
static from(optionsOrLoader: TItemsOrLoader, opt?: ProEnumOption) {
return new ProEnum(optionsOrLoader, opt);
}
static is(x: any): x is ProEnum {
return x instanceof ProEnum;
}
isAsync = false;
remapPropName: string | null = null;
options: ProEnumItem[] = [];
loader(params?: any): Promise<ProEnumItem[]> {
return Promise.resolve(this.options);
}
}
Schema 属性
在 Schema 表达式中, 使用 x-data#enum 这个字段可以添加一些属性
{
"proEnum": {
"type": "string",
"x-data": {
"enum": {
"mapToProp": "loadData",
// TODO: test compile
"params": "{{object or expression}}",
}
}
}
}