表单

Form 用于按字段配置渲染表单,并内置 Validator 验证模块与提交数据收集。

defineComponent

示例

点击展开查看详情

导入

JavaScript
import { createForm } from 'vanilla-jui';

基础用法

使用 createForm(props) 创建表单实例:

JavaScript
const form = createForm({ fields: [ { type: 'email', payload: { label: 'Email address', name: 'email', placeholder: 'Enter email', required: true, }, }, ], validator: { rules: { email: { required: true, email: true }, }, messages: { email: { required: 'Email required', email: 'Invalid email' }, }, }, onSubmit: async (data, form) => { form.state.submitting = true; await saveUser(data); form.setState({ submitting: false }); },}).mount('.form-demo');
  • createForm(props) 只创建实例并初始化状态,不会立即创建 DOM。
  • 调用 build() 后只会构建表单根节点,不会自动挂载。
  • 调用 mount(container) 挂载到指定容器,或使用表单根节点 form.element 手动挂载。

参数

createForm(props)

参数 类型 默认值 说明
fields Array<FormItem> [] 表单项配置,也是动态表单责任链入口
validator object {} 传给 Validator 验证模块的 rulesmessagesvanilla 等配置
onSubmit Function | null null 校验通过后触发,参数为 (data, form)
onReset Function | null null 重置时触发,参数为 (event, form)
id string | null 自动生成 表单根节点 id
style string | object '' 表单根节点内联样式
buttons boolean | string 见下表 移除或反转按钮位置
buttonsPosition 'start' | 'center' | 'end' 'start' 按钮组水平位置
size 'sm' | 'md' | 'lg' 'md' 表单大小
className object 见下表 自定义表单样式类类

fields

格式:Array<FormItem>

每个控件 FormItem 是一个对象,包含 { type, payload, next? }。固定表单可以只配置 typepayload;动态表单通过 next(current, acients) 覆盖默认数组顺序,按当前字段值决定下一个表单项。

  • type:控件类型,如 text, emailpasswordselect, radio, checkbox, switch, file, custom 等。
  • payload:控件配置,包含 labelname 等属性。
  • next:下一个控件,用于动态表单责任链。

常用 payload 属性:

属性 说明
label 字段标签;传 false 或省略时不渲染标签
name 表单字段名,用于 FormData 和 Validator 规则匹配
options selectradio、多选 checkbox 的选项数组
value 默认值;多选 checkbox 可传数组
checked 单个 checkbox 或 switch 的默认选中状态
required 必填标记,渲染原生 required 属性
placeholder 输入提示
autocomplete 仅适用于支持该属性的具体控件,如 input、textarea等
help 字段下方帮助文本
disabled 禁用控件
readonly 只读控件
content type: 'custom' 时渲染的自定义内容

责任链

(current, acients) => FormItem \| null

责任链展开有内部保护上限:单次渲染最多展开 1000 个表单项,用于防止错误的 next() 循环或永不终止的动态链。它不是业务字段数量配置;正常表单不需要感知这个上限。

示例,根据 select 控件值动态切换下一个表单项:

JavaScript
const input = { type: 'text', payload: { label: 'Dynamic Input', name: 'dynamicValue', }, next: null,};const textarea = { type: 'textarea', payload: { label: 'Dynamic Textarea', name: 'dynamicValue', }, next: null,};const selector = { type: 'select', payload: { label: 'Next Field Type', name: 'fieldType', value: 'input', required: true, options: [ { value: 'input', text: 'Render input next' }, { value: 'textarea', text: 'Render textarea next' }, ], }, next(current) { return current.payload.value === 'textarea' ? textarea : input; },};const form = createForm({ fields: [selector],}).mount(document.querySelector('#demo'));

buttons

buttons: false 时不渲染按钮组,适合由外部容器通过实例属性或实例方法 requestSubmit() 自定义交互时机和行为。

className

自定义样式类。className 配置包含以下字段:

属性 默认值 说明
form j-form 表单容器
item form-field 表单项容器
label field-legend 表单项标签
required is-required 必填标记
control field-control 表单项控件容器
helpInvalid is-invalid 无效状态提示
buttons form-buttons 按钮组容器
button j-button 通用按钮
submitBtn is-primary 提交按钮
resetBtn is-ghost 重置按钮
input j-input 输入框
textarea j-textarea 文本域
select j-select 选择框
radio j-radio 单选框
checkbox j-checkbox 多选框
choiceGroup is-group 多选控件分组布局
radioLabel radio-label 单选框标签
radioText radio-text 单选框文本
switch j-switch is-default 开关
switchSlider switch-slider 开关滑块

实例属性

属性 说明
props 归一化后的初始化配置
state 响应式状态对象,也是运行时 UI 的主要来源
runtime.built 是否已创建 owned view
runtime.mounted 根节点当前是否挂载
runtime.destroyed 实例是否已销毁
element build 后的稳定根节点

state

把运行时需要关注的数据放入响应式 state

字段 说明
fields 表单项数据列表
submitting 是否正在提交表单
  • fields:更新状态,触发表单渲染。
  • submitting:更新状态,触发表单提交动画。

实例方法

方法 说明
validate() 执行内置 Validator 校验,返回是否通过
collectData() 返回当前 FormData 汇总后的普通对象
build() 构建 DOM;只生成 root,不自动挂载
mount(container) 构建并挂载根节点
unmount() 移除根节点,保留 state 和 view owner
requestSubmit() 触发表单提交
reset() 重置校验状态和提交数据
setFields(fields) 更新响应式 state.fields,由责任链和 keyed 列表更新字段
resetFields() 恢复初始化字段
setState(patch) 更新响应式状态字段
destroy() 销毁实例,释放 Validator、渲染和事件资源
  • 校验规则复用 Validator 验证模块的规则与消息格式。
  • 需要优先使用浏览器原生表单验证能力时,设置 validator.vanilla: true
最后更新于 2026-09-22 17:30:16 UTC+8