ConfigForm 配置表单
介绍
预设表单项目,通过配置生成表单,简化表单编码。
组合使用 config-form、config-footer,覆盖校验、条件显隐、回显格式化与底部操作等常见场景;可与 config-list、config-detail 搭配完成 CRUD。
基础用法
传入 data(表单值)、items(字段配置)、actions(底部按钮,可选):
html
<config-form
:data="form"
:items="formItems"
:actions="formActions"
/>ts
import ConfigForm from '@/composites/config-form/index.vue';
import type { FormItem, FormAction } from '@/composites/config-form/types';
const form = ref<any>({});
const formItems = ref<FormItem[]>([
{
key: 'title',
label: '标题',
component: 'input',
rules: ['required'],
placeholder: '请输入标题',
},
{
key: 'status',
label: '状态',
component: 'radio',
options: [
{ label: '待处理', value: 'todo' },
{ label: '进行中', value: 'doing' },
],
},
]);
const formActions = ref<FormAction[]>([
{
title: '提交',
name: 'submit', // 会先校验,通过后再执行 action
type: 'primary',
action: (data) => {
console.log('提交值', data);
},
},
]);组件 Props
| 属性 | 说明 | 默认 |
|---|---|---|
data | 表单数据对象(双向绑定字段值) | — |
items | 字段配置列表 | — |
actions | 底部操作(走 config-footer) | — |
theme | 主题:default / card | card |
labelPosition | 标签位置:left / top | top |
requiredPosition | 必填星号位置:left / right | right |
scrollOffsetTop | 校验失败滚动额外偏移 | 0 |
字段配置
每个字段至少需要 key、component;常用项如下:
| 字段 | 说明 |
|---|---|
key | 数据键,唯一 |
label | 标签文案 |
component | 控件类型,见下表 |
rules | 校验:'required' / 'phone' / 'email' / 'idcard' 或自定义 FormItemRule |
placeholder | 占位;必填失败时也会用于提示 |
options | 选项(radio / checkbox / picker / select / cascader) |
attrs | 透传到底层控件的属性 |
show | 是否展示(仍占位/仍在表单中),可为函数 (form, value) => boolean |
visible | 是否渲染;false 时不挂载该项,可为函数 |
formatter | 展示用格式化 (value, form) => any |
dataKey | getData() 提交时的键名映射 |
dataFormatter | getData() 提交时的值格式化 |
onChange | 值变化回调 |
支持的 component
| component | 说明 |
|---|---|
input | 输入框,可配 unit |
number | 数字,type: 'int' | 'float',可配 unit |
textarea | 多行文本 |
rate | 评分 |
radio | 单选 |
checkbox | 多选 |
picker | 选择器 |
select | 选择组,可 multiple |
cascader | 级联,可 multiple |
date | 日期,type 支持 year / year-month / month-day / date |
datetime | 日期时间,timeType: 'minute' | 'second' |
calendar | 日历,可配 minDate / maxDate / disabled |
upload | 上传,可配 minSize / maxSize(MB) |
TIP
小程序不支持动态组件,字段需在 config-form 内静态引入;扩展新类型时在 composites 中增加对应 fields/* 并注册分支。
底部操作
actions 中 name: 'submit' 的按钮会先执行表单校验,通过后再调用 action(data);data 为 getData() 的结果(含 dataKey / dataFormatter 映射)。
ts
const formActions = ref<FormAction[]>([
{
title: '取消',
plain: true,
action: () => uni.navigateBack(),
},
{
title: '保存',
name: 'submit',
type: 'primary',
action: async (data) => {
await saveApi(data);
},
},
]);也可不传 actions,自行用 ref 调用实例方法:validate、getData、clearValidate 等。
条件显隐
visible:为false时不渲染字段(带动画收起),适合问卷分支。show:为false时隐藏但仍保留在表单结构中。
ts
{
key: 'otherHero',
label: '其他英雄',
component: 'input',
rules: ['required'],
visible: (form) => form.played === '1' && form.hero === '0',
}回显与提交映射
表单内部可用中文 key 绑定;提交时用 dataKey / dataFormatter 转成接口字段:
ts
{
key: '昵称',
label: '昵称',
component: 'input',
dataKey: 'nickname',
dataFormatter: (value) => String(value).trim(),
}formatter 只影响控件展示值,不改变 data[key] 原始存储(除非配合 onChange 自行写入)。
注意事项
data需是响应式对象(ref/reactive),字段写入依赖同一引用。key必须唯一,并与data上的字段对应。- 选项类字段提供
options(或返回选项的函数);级联数据结构需符合控件约定。 showvsvisible:要「不占位、不参与展示」用visible;仅视觉隐藏用show。- 提交取值用
getData()(或name: 'submit'的action参数),不要只读原始data若已配置dataKey。 - 本案例源码在
example/src/composites/config-form,可按业务拷贝改造。
错误示范
不要把非响应式普通对象当 data
ts
// ❌ 错误:赋值后视图不更新
const form = { title: '' };
// ✅ 正确
const form = ref({ title: '' });
// 或
const form = reactive({ title: '' });不要混淆 show / visible
ts
// ❌ 错误:以为 show: false 会卸载字段,实际仍在表单中
{ key: 'a', component: 'input', show: () => false }
// ✅ 分支问卷、不渲染时用 visible
{ key: 'a', component: 'input', visible: (form) => form.type === '1' }不要漏配 options
ts
// ❌ 错误:radio / picker 等无选项
{ key: 'status', component: 'radio', rules: ['required'] }
// ✅ 正确
{
key: 'status',
component: 'radio',
rules: ['required'],
options: [
{ label: '启用', value: '1' },
{ label: '停用', value: '0' },
],
}提交勿忽略 dataKey
ts
// ❌ 错误:配置了 dataKey 却直接把 form 原样 POST
await api(form.value);
// ✅ 正确:用 getData() 或 submit action 的 data
const data = formRef.value?.getData();
await api(data);