Skip to content

FForm 配置化表单 ​

FForm 是基于 Vue 3 与 Element Plus 的配置化表单组件,支持字段注册表、响应式联动、分区、脏状态、异步校验、提交状态和值转换。

使用组件 FForm。字段配置统一使用 schemas、field、component 和 F 前缀内置组件名。

使用方式 ​

Hooks 模式 ​

useForm 返回 [register, methods]。@register 的作用是把已挂载的 FForm 实例交给 methods,并不是触发表单渲染;忘记绑定时表单仍可渲染,但 Hook 方法没有可操作的实例。

vue
<template>
  <FForm @register="register" @submit="handleSubmit" />
</template>

<script setup lang="ts">
import { FForm, useForm } from '@axewo/fin-ui'

const [register, methods] = useForm({
  schemas: [
    { field: 'name', label: '姓名', component: 'FInput', required: true },
    { field: 'age', label: '年龄', component: 'FInputNumber' },
  ],
  actions: { submit: '提交', reset: '重置' },
})

function handleSubmit(values: Record<string, any>) {
  console.log(values)
}
</script>

在组件挂载后(例如事件处理函数或 onMounted 中)调用 methods。每个表单应使用独立的 useForm 实例。

Props 模式 ​

vue
<template>
  <FForm v-model="formData" :config="formConfig" @submit="handleSubmit" />
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { FForm, type UseFormProps } from '@axewo/fin-ui'

const formData = ref({ name: '', age: 18 })
const formConfig: UseFormProps = {
  schemas: [
    { field: 'name', label: '姓名', component: 'FInput' },
    { field: 'age', label: '年龄', component: 'FInputNumber' },
  ],
}

function handleSubmit(values: Record<string, any>) {
  console.log(values)
}
</script>

config 可响应式更新;新的 schemas、sections、mode、scene 和 syncMode 会同步到表单内部。配置类型为 UseFormProps,普通字段使用 schemas,分区字段使用 sections[].items。

示例 ​

loading
loading
loading
loading
loading
loading
loading
loading
loading
loading

配置语义 ​

schemas 与 sections ​

  • schemas 定义普通表单的字段。
  • 设置非空 sections 后进入分区模式,字段由各分区的 items 提供,schemas 不参与渲染和提交。
  • section.hidden 可传布尔值或 (values) => boolean;collapsed 当前仅为配置字段,不负责折叠交互。

重置与脏状态 ​

表单会为当前值建立基线快照:初次初始化(包含 defaultValue)建立初始基线,父组件外部回填新的 v-model 值会建立新基线。字段编辑后 isDirty 变为 true。

  • resetFields():恢复基线并清除校验;无论 syncMode 为何,重置值都会立即同步给父组件。
  • takeSnapshot():把当前值设为新的已保存基线。
  • resetToSnapshot():直接恢复当前基线,适合自定义操作栏。
  • Schema 更新只会为新增且尚无值的字段补 defaultValue,不会覆盖未保存编辑,也不会整体重建基线。

syncMode ​

值update:modelValue 时机
realtime字段变化后(默认)
blur字段失焦时
submit校验通过并提交时

程序调用 setFieldsValue() 仍会更新内部模型并参与脏状态比较;重置始终立即向外同步。

reactions ​

每条联动配置必须声明 dependencies:

  • handler(values, schema) 派生当前字段的 Schema(例如 ifShow、disabled);只有依赖值均非空时执行。
  • setOptions(values) 可同步或异步返回当前字段的新选项;后发请求优先,旧异步结果不会覆盖新结果。
  • resetFields 在依赖值实际变化后清空指定字段;初始化监听不会误清空已有值。
ts
{
  field: 'account',
  component: 'FSelect',
  reactions: [{
    dependencies: ['voucherType'],
    setOptions: values => accountOptions[values.voucherType] ?? [],
    resetFields: ['account'],
  }],
}

FormSchema 常用配置 ​

属性类型说明
fieldstring必填,模型中的唯一字段名
labelstring表单项标签
componentstring | Component注册表名称或 Vue 组件,默认按 F 前缀书写
componentPropsobject | (params) => object透传给字段组件的属性
colProps / spanColProps / number栅格配置与简写
defaultValueany字段没有值时使用的默认值
required / rulesboolean | string / FormRule[]必填简写与字段自定义规则;集中合并至父级 ElForm.rules
asyncValidator(value, values) => Promise<string | null>FormRule 的异步校验简写,返回错误信息或 null
ifShowboolean | (params) => boolean是否渲染字段
disabledboolean静态禁用
dynamicDisabled(params) => boolean动态禁用
optionsFieldOption[] | () => Promise<FieldOption[]>静态或异步选项
transform(value, values) => any仅转换提交结果,不改写表单模型
reactionsFieldReaction[]字段联动
render(params: FormFieldRenderParams) => VNodeChild完整接管表单项内部内容,支持文本、VNode 与组件 VNode
slotNamestring字段具名插槽名称,默认使用 field

自定义字段内容 ​

render 与字段具名插槽都可以完整接管 ElFormItem 内部内容,但字段仍保留在表单模型、校验和提交数据中。两者在编辑与查看模式下都生效:配置了 schema.render 时,以 render 为准,具名插槽不生效。render 返回 undefined 时直接恢复当前模式的标准渲染;返回 null 或空字符串仍表示有意渲染为空,不会回退。未配置 render 时才尝试具名插槽;空插槽(例如仅转发、没有实际内容)不会阻止标准渲染。

例如编辑时下拉框使用后端编码,查看时展示后端返回的名称:

ts
{
  field: 'statusCode',
  component: 'FSelect',
  options: statusOptions,
  render: ({ mode, model }) =>
    mode === 'view' ? model.statusName || '--' : undefined,
}

此时编辑模式仍由 FSelect 绑定 statusCode,查看模式只展示 statusName,不会改写模型中的编码。

ts
import { h } from 'vue'
import { ElTag } from 'element-plus'

const schemas = [
  {
    field: 'creator',
    label: '创建人',
    render: ({ value }) => value || '--',
  },
  {
    field: 'status',
    label: '状态',
    render: ({ value }) => h(ElTag, null, () => value),
  },
  {
    field: 'approved',
    label: '审核结果',
    render: ({ value, setValue }) =>
      h('button', { type: 'button', onClick: () => setValue(!value) }, value ? '已通过' : '未通过'),
  },
]

回调参数还包含 model、schema、schemas、scene、mode、options、componentProps、disabled 和 formActionType。仅当字段未配置 render 时,才使用父组件提供的与 slotName || field 同名的插槽;插槽接收相同上下文:

vue
<FForm :config="formConfig">
  <template #creator="{ value, mode }">
    <span>{{ value }}({{ mode }})</span>
  </template>
</FForm>

查看模式的多语言与数据字典 ​

设置 mode: 'view' 时,FLangInput 会按照当前界面语言从多语言对象中选取文本;当前语言没有值时依次回退中文和首个非空翻译。FDictSelect、FDictRadio 则展示字典项的 label,而不是存储在模型中的编码:可通过 dictType 读取 FinConfigProvider 提供的静态字典或异步加载结果;componentProps.fieldNames 可指定字典字段映射。字段的 componentProps.options、options 优先于全局字典。字典项暂未加载或无法匹配时展示原始值。

ts
const formConfig: UseFormProps = {
  mode: 'view',
  schemas: [
    { field: 'name', label: '名称', component: 'FLangInput' },
    { field: 'status', label: '状态', component: 'FDictSelect', dictType: 'status' },
  ],
}

需要完全自定义某个字段的只读内容时,仍可配置 render 或具名插槽。

自定义校验规则 ​

字段 schema.rules 与表单级 config.rules[field] 都支持 Element Plus 标准规则(例如 pattern、type、validator、trigger),同一字段按 required 简写、表单级规则、字段规则的顺序执行,不会相互覆盖。字段也可使用 asyncValidator(value, formValues),返回错误字符串表示失败,返回 null 表示通过。

ts
const formConfig: UseFormProps = {
  rules: {
    email: [{ type: 'email', message: '邮箱格式不正确', trigger: 'blur' }],
  },
  schemas: [
    {
      field: 'email',
      component: 'FInput',
      required: '请输入邮箱',
      rules: [
        {
          validator: (_rule, value, callback) =>
            callback(value.includes('@example.com') ? undefined : new Error('请使用公司邮箱')),
        },
      ],
    },
  ],
}

规则统一挂载到父级 ElForm;字段渲染器只设置 ElFormItem.prop 进行关联,不在 ElFormItem 上重复绑定 rules。查看模式不执行表单校验。

FormMethods API ​

ts
const [register, methods] = useForm(config)
方法返回值说明
getFieldsValue()Record<string, any>获取当前值
setFieldsValue(values)void部分更新字段值
resetFields()Promise<void>恢复基线并清除校验
validate()Promise<void>校验全部字段;失败时 reject
validateFields(names?)Promise<void>校验指定字段;失败时 reject
clearValidate(names?)Promise<void>清除校验状态
submit()Promise<void>触发表单提交流程
scrollToField(name)void滚动到字段
setProps(props)Promise<void>更新表单配置
updateSchema(data)Promise<void>按 field 增量更新 Schema
appendSchemaByField(schema, afterField?, first?)Promise<void>添加字段
removeSchemaByField(fields)Promise<void>删除字段
watchField(field, callback, options?)() => void监听字段并返回停止函数
setMode(mode)void切换 edit / view

响应式状态包括 formModel、isDirty、submitting、isCollapsed 和 mode。它们在 useForm 返回值上是 Ref;模板会自动解包,脚本中读取状态请使用 .value。

内置组件与扩展 ​

实际内置字段类型和自定义注册方式见: