Form 表单
表单封装层 —— 统一 label / 必填星号 / 提示文案 / 错误展示,把所有现有 input 接进来。
基础用法
<CfForm> 提供布局上下文,<CfFormField> 包裹每一个表单项,统一渲染 label、必填星号、提示 / 错误文案。校验逻辑由用户自行实现,组件只负责把 error 显示出来并标红控件边框。
<CfForm layout="vertical">
<CfFormField label="姓名">
<CfInput v-model="name" placeholder="张三" />
</CfFormField>
<CfFormField label="邮箱" hint="用于登录">
<CfInput v-model="email" type="email" />
</CfFormField>
<CfButton>提交</CfButton>
</CfForm> <CfForm layout="vertical">
<CfFormField label="姓名">
<CfInput value={name} onChange={(e) => setName(e.target.value)} placeholder="张三" />
</CfFormField>
<CfFormField label="邮箱" hint="用于登录">
<CfInput value={email} onChange={(e) => setEmail(e.target.value)} type="email" />
</CfFormField>
<CfButton>提交</CfButton>
</CfForm> 三种布局
layout 决定 label 和控件的排列方式:
vertical(默认)—— label 在控件上方,最常见的填表样式horizontal—— label 与控件同行,配合labelWidth对齐inline—— 所有字段挤在一行,常用于搜索条 / 工具栏
layout = vertical(默认)
layout = horizontal
layout = inline
<CfForm layout="vertical">…</CfForm>
<CfForm layout="horizontal" :label-width="80">…</CfForm>
<CfForm layout="inline">…</CfForm> <CfForm layout="vertical">…</CfForm>
<CfForm layout="horizontal" labelWidth={80}>…</CfForm>
<CfForm layout="inline">…</CfForm> 校验与错误
required 在 label 后加红色 ✱;hint 在控件下方挂提示文案;error 非空时控件边框变红,错误文案替换掉 hint 显示。校验逻辑(同步 / 异步 / 第三方库)完全由父组件控制 — 组件只把 error 显示出来。
function submit() {
errors.value = {};
if (!name.value.trim()) errors.value.name = '姓名不能为空';
if (!email.value.includes('@')) errors.value.email = '邮箱格式不正确';
}
<CfForm layout="vertical">
<CfFormField label="姓名" required :error="errors.name">
<CfInput v-model="name" />
</CfFormField>
<CfFormField label="邮箱" required hint="用于登录" :error="errors.email">
<CfInput v-model="email" type="email" />
</CfFormField>
<CfButton @click="submit">提交</CfButton>
</CfForm> function submit() {
const next: Record<string, string> = {};
if (!name.trim()) next.name = '姓名不能为空';
if (!email.includes('@')) next.email = '邮箱格式不正确';
setErrors(next);
}
<CfForm layout="vertical">
<CfFormField label="姓名" required error={errors.name}>
<CfInput value={name} onChange={(e) => setName(e.target.value)} />
</CfFormField>
<CfFormField label="邮箱" required hint="用于登录" error={errors.email}>
<CfInput value={email} onChange={(e) => setEmail(e.target.value)} type="email" />
</CfFormField>
<CfButton onClick={submit}>提交</CfButton>
</CfForm> 复杂表单
混合 Input / Select / Textarea / Button 的真实表单模板。
<CfForm layout="vertical">
<CfFormField label="姓名" required><CfInput v-model="name" /></CfFormField>
<CfFormField label="邮箱" required hint="用于登录"><CfInput v-model="email" type="email" /></CfFormField>
<CfFormField label="角色"><CfSelect v-model="role" :options="roles" /></CfFormField>
<CfFormField label="简介"><CfTextarea v-model="bio" :rows="3" /></CfFormField>
<CfButton>提交</CfButton>
</CfForm> <CfForm layout="vertical">
<CfFormField label="姓名" required><CfInput ... /></CfFormField>
<CfFormField label="邮箱" required hint="用于登录"><CfInput ... type="email" /></CfFormField>
<CfFormField label="角色"><CfSelect value={role} onChange={setRole} options={roles} /></CfFormField>
<CfFormField label="简介"><CfTextarea value={bio} rows={3} ... /></CfFormField>
<CfButton>提交</CfButton>
</CfForm> API · Form Props
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
layout | 'vertical' | 'horizontal' | 'inline' | 'vertical' | 整体布局 |
size | 'sm' | 'md' | 'lg' | 'md' | 默认尺寸(暂为视觉占位,未与控件 size 联动) |
labelWidth | number | string | — | 仅 horizontal 布局生效,固定 label 宽度 |
disabled | boolean | false | 全局禁用(暂未与控件 disabled 联动,需要手动透传) |
API · FormField Props
| 属性 | 类型 | 说明 |
|---|---|---|
label | string | ReactNode | 标签文案 |
required | boolean | 显示必填星号 |
hint | string | ReactNode | 控件下方提示文案 |
error | string | ReactNode | 错误文案;非空时控件边框变红 |
for (Vue) / htmlFor (React) | string | 自定义 input id;省略则自动生成 |
layout | FormLayout | 覆盖父级 Form 布局(单字段调整) |
反馈与讨论
Form 表单 的讨论