ElFormBuilder
ElFormBuilder 用 EllFormSchema[] 描述整表:经 parseSchema 切成 fields / group / custom 块,在 el-form 内组合 ElFormLayout、ElFormGroup 与 ElFormRenderer,并通过 portal-vue 将 保存 / 提交 / 重置 等操作投递到外部 PortalTarget(如 ${uid}-actions)。适合 CRUD、分步表单等与 ElCruPage 配合的场景。
前置阅读
- 单字段控件与
controlType:FormRenderer - 字段类型
EllFieldSchema、dependencies、visible:@element-plus-lab/utils(主包export type白名单) - 网格与 Provider:ConfigProvider
基础用法
v-model 绑定整表数据对象;schema 为混合数组(扁平字段、type: 'group' 分组、type: 'custom' 自定义块)。
两种表单联动方式(重点)
联动均依赖 model(及可选 active-tab)变化重算;最终在表单项上体现为 显隐、禁用、必填、规则、控件 props 等。显隐由下列两种方式共同参与(见下一小节「组合规则」)。
方式一:dependencies 声明式联动
推荐用 resolve({ values, actions }) 一次返回显隐 / 必填 / 控件 props,并用 actions.setFieldValue 改其它字段。旧的多回调(show / required / controlConfig 等)仍可用。
controlConfig 不会写回 model
controlConfig 对齐 Vben 的 componentProps:只合并进控件 props。在回调里 return { ...values, someField: undefined } 不会清空表单值。改 model 必须 actions.setFieldValue(写在 resolve 或旧的 trigger 里)。
evaluateFieldDependencies(渲染路径)里的 actions 是空操作,避免在模板求值时改值;真正写回由 ElFormBuilder / ElFormQuery 内部的 bindFormDependencyEffects 在 triggerFields 变化时执行。被重置的字段不要放进 triggerFields,以免循环。
| 键 | 类型 | 作用 |
|---|---|---|
triggerFields | string[] | 跟踪哪些 model 键;resolve / trigger 的副作用必填,否则不会写值。不传则依赖 model 顶层全部键 |
resolve | (ctx) => state | 推荐。ctx:{ values, actions, schema }。返回 show / if / disabled / required / rules / controlConfig;改值用 actions.setFieldValue |
show | (values) => boolean | 旧写法:为假时不挂载该项(不参与校验) |
if | (values) => boolean | 旧写法:为假时不挂载,且跳过其余 UI 求值 |
disabled | (values) => boolean | 为真时禁用控件;为假时在 mode: 'disabled' 下可局部放开 |
required | (values) => boolean | 动态 el-form-item required |
rules | (values) => unknown | 动态规则;返回 undefined 时保留 formItemConfig.rules |
controlConfig | (values) => object | 与静态 controlConfig 合并(只改控件 props) |
trigger | (values, actions) => void | 旧写法:专门写 model;与 show 等可并存 |
一次 model 变更会对相关字段调用 evaluateFieldDependencies,结果传入 ElFormRenderer(dependency-eval),避免重复执行用户函数。
旧回调(仍可用):
推荐:resolve + setFieldValue:
方式二:visible(payload) 函数式显隐
字段上配置 visible 函数,入参 EllFieldVisiblePayload:
| 字段 | 含义 |
|---|---|
tab | 来自 ElFormBuilder 的 active-tab(未传为 ''),用于多 Tab 分区 |
model | 当前整表数据 |
index | 字段在当前 schema 列表层的下标(根 fields 块、分组 children 各自从 0 计数) |
schema | 当前字段项数据子集 |
适用于:分区 / 选项卡显隐、与序号相关的展示条件等;不代替 dependencies 的 show——二者为 且 关系。
组合规则与建议
- 最终是否挂载:
resolveFieldItemVisible:先dependencies.show(或resolve返回的show/if,缺省true),再与visible(payload)(缺省true)逻辑与。 - 优先
triggerFields: 字段多、依赖面窄时务必写上,减少无意义重算与模板依赖抖动;resolve/trigger写值时必填。 - 选型建议:
- 以业务字段值驱动的显隐 / 必填 / 规则 / 控件 props / 改其它字段 → 优先
dependencies.resolve; - 以 Tab / 分区、或强依赖
index的规则 → 用visible(仍可再叠加dependencies做必填等)。
- 以业务字段值驱动的显隐 / 必填 / 规则 / 控件 props / 改其它字段 → 优先
其它联动补充:schema.events 可在用户操作时执行业务逻辑(与 FormRenderer 增强 payload 配合)。
Schema 与解析块
parseSchema(utils)将数组规范为块序列:相邻字段合并为fields;group含children与可选layoutConfig;custom支持render或 portal 占位。- 分组:
ElFormGroup+ 内层ElFormLayout;详见 表单方案。
网格与表单项
grid/fixed-col-count/col-gap:与ElFormLayout一致;row-gap在 Builder 上默认0,需纵向间距时显式传row-gap。compact:grid未写列间距时可默认 8px;并挂载紧凑样式类。label-width/label-config/form-config:经mergeElFormBuilderBind合并进el-form;字段级labelConfig仍优先。
模式 mode
与 ElFormRenderer 一致:edit(默认)、disabled、preview(不注册控件 ref)。
操作与 portal
actions:EllActionConfig[](key/to/order/text/buttonProps/render)。内置submit(校验后提交)、save、reset** 的默认顺序与portal的order见实现。submit-handler/save-handler/reset-handler:拦截对应默认行为。- 表级靶位:
${uid}-form-header、${uid}-form-footer;分组 / 自定义块另有${uid}-${field}-…(与ElCruPage文档一致)。 - 默认插槽: 可注入
Portal;useFormDialog的renderFormSlot即写入此槽,payload.uid与 Builderuid相同。 uid:未传ulid();与页头PortalTarget共用时请固定传入同一值。
初始值与重置
initial-values:resetFields后把model恢复为与el-form对齐的快照(与reset-handler二选一逻辑以实现为准)。
暴露(defineExpose)
| 名称 | 说明 |
|---|---|
model / formRef | 与 v-model、el-form 同源 |
uid | 实例 id |
mergedGridLayout / parsedBlocks | 合并后网格、解析块 |
formItemRef / getControlRef / getFormItemRef | 字段实例访问 |
getSchemaByField(getSchema) | 查字段 schema |
formHeaderPortalName / formFooterPortalName | 表级 portal 名字符串 |
事件
| 事件 | 说明 |
|---|---|
| submit | 校验通过且未由 submit-handler 吞掉 |
| save / reset | 对应按钮 |
| validate-failed | 校验失败 |
| action | 自定义 action.key |
Props(摘要)
| 属性 | 说明 |
|---|---|
modelValue(v-model) | 整表数据(必填) |
schema | EllFormSchema[](必填) |
initial-values | 重置恢复用 |
uid | portal 前缀 |
grid / fixed-col-count / col-gap / row-gap / compact | 网格 |
label-width / label-config / form-config | 表级标签与 el-form 透传 |
mode | edit / disabled / preview |
active-tab | 供 visible(payload.tab) |
actions / submit-handler / save-handler / reset-handler | 工具栏与提交语义 |
类型说明
import type {
ElFormBuilderProps,
EllFormSchema,
EllActionConfig,
} from 'element-plus-lab'dependencies 与 visible(utils 摘录)
export type EllFieldSchemaDependencies =
| EllFieldSchemaDependenciesResolve
| EllFieldSchemaDependenciesLegacy
export interface EllFormDependencyResolveContext {
values: Record<string, unknown>
actions: EllFormDependencyActions
schema: { fieldName: string }
}
/** 推荐:resolve + actions.setFieldValue */
export interface EllFieldSchemaDependenciesResolve {
triggerFields?: string[]
resolve: (ctx: EllFormDependencyResolveContext) => EllFormDependenciesResolvedState
}
/** 旧多回调;controlConfig 只改控件 props */
export interface EllFieldSchemaDependenciesLegacy {
triggerFields?: string[]
if?: (values: Record<string, unknown>) => boolean
show?: (values: Record<string, unknown>) => boolean
disabled?: (values: Record<string, unknown>) => boolean
required?: (values: Record<string, unknown>) => boolean
rules?: (values: Record<string, unknown>) => unknown
controlConfig?: (values: Record<string, unknown>) => Record<string, unknown>
trigger?: (values: Record<string, unknown>, actions: EllFormDependencyActions) => void
}
/** payload.schema:与 utils 中 EllFieldSchemaBase 对齐 */
export interface EllFieldVisiblePayload {
tab: string
model: Record<string, unknown>
index: number
schema: EllFieldSchemaBase
}显隐: evaluateFieldDependencies 得到 dep.show(未配置 dependencies 或 show / if 时为真),再与 visible:未配置 或 visible(payload) 为真;二者同时为真才挂载。
完整
ElFormBuilderProps以发布包d.ts为准。
相关
- FormRenderer、FormLayout、FormQuery
- CruPage:
ElFormBuilder典型落地 - 表单方案
贡献者
jenemy