简体中文
fs-form
约 2065 字大约 7 分钟
2026-06-25
简介
fs-form 对标 Element UI Form,用于收集、校验与提交表单数据。由 fs-form(表单容器)、fs-form-item(表单项,含 label、错误信息、必填标记)、以及表单项内容控件(如 fs-input)组成。支持统一或按项配置校验规则(required、pattern、min/max/len、whitespace、自定义 validator),支持 trigger:blur / change / submit 控制校验触发时机,支持多种字段布局(左右/上下、左对齐/中线对齐等)。
UI设计:https://www.figma.com/design/ULbC0RoBVE9UHOPZxrpLIz/%E5%B0%8F%E7%A8%8B%E5%BA%8F%E5%9F%BA%E7%A1%80%E7%BB%84%E4%BB%B6%E8%AE%BE%E8%AE%A1%E8%A7%84%E8%8C%83?node-id=6895-99499&p=f
使用方法
局部引入时,在页面的 index.json 中配置(fs-form 依赖 fs-form-item,表单项内容需单独引入如 fs-form-input):
"usingComponents": {
"fs-form": "/avaui-sub/fs-form/index",
"fs-form-item": "/avaui-sub/fs-form/fs-form-item/index",
"fs-form-input": "/avaui-sub/fs-form/fs-form-input/index"
}PWC(自定义组件/插件)使用:仅组件 usingComponents 注册方式遵循以下格式(avaComponent:// 协议,其他用法与局部引入一致。
"usingComponents": {
"fs-form": "avaComponent://avaui-sub/fs-form/index",
"fs-form-item": "avaComponent://avaui-sub/fs-form/fs-form-item/index",
"fs-form-input": "avaComponent://avaui-sub/fs-form/fs-form-input/index"
}代码演示
以下章节顺序与 demo 预览一致,便于对照查看。
1. 基础用法
通过 model 绑定表单数据、rules 绑定校验规则,fs-form-item 的 prop 对应 model 字段名。提交时通过 selectComponent 获取表单实例后调用 validate() 与 getValue()。
支持多种表单项类型:
- 文本输入:使用
fs-form-input组件,支持type="text"(单行)和type="textarea"(多行文本域) - 单选:使用
fs-form-radio组件,value为单个值 - 多选:使用
fs-form-checkbox组件,value为数组,校验时需设置type: 'array'
2. 对齐方式(fieldAlign)
通过 fs-form 的 fieldAlign 统一设置所有表单项的布局,或通过 fs-form-item 的 fieldAlign 单独覆盖。可选值:left(左右-左对齐)、top_and_bottom(上下)、center(左右-中线对齐)、whole_left(左右-内容紧跟 label)。
3. 表单校验:必填与格式
规则与 async-validator 对齐,支持 required、message、pattern(正则,字符串会转 RegExp)、min/max/len(长度或数值)、whitespace: true(不允许纯空格)。
4. 校验触发时机(trigger)
与 Element UI 一致,支持 trigger: 'blur'(失焦)、trigger: 'change'(值变更)、trigger: 'submit'(仅提交时触发)。不写 trigger 则在 blur、change、submit 时都会参与校验。提交时始终校验全部规则,不受 trigger 限制。
5. 自定义校验(validator)
支持自定义规则,仅支持 Promise 写法:resolve() 表示通过,reject(error) 或 reject([error, ...]) 表示不通过(error 可为 string 或 Error)。
6. 自定义表单项内容
fs-form-item 通过捕获插槽内容的 change 和 blur 事件来更新校验状态。因此,自定义表单项内容组件需满足以下规范:
- Props: 接收
value属性用于回显。 - Events:
- 值变更时触发
change事件,detail中包含{ value: newValue }。 - 失焦时触发
blur事件(可选,用于 blur 校验)。 - 重要:事件必须开启冒泡
bubbles: true和composed: true,以便fs-form-item监听到。
- 值变更时触发
自定义组件示例 (my-mood)
// my-mood/index.js
Component({
properties: { value: String },
methods: {
onTap(e) {
const val = e.currentTarget.dataset.val;
this.setData({ value: val });
// 关键:触发 change 事件,并设置 bubbles: true 让 fs-form-item 捕获
this.triggerEvent('change', { value: val }, { bubbles: true, composed: true });
}
}
});7. Wrapper 封装场景(formId)
在使用 wrapper 组件封装 fs-form-item 时,由于微信小程序 relations 机制可能失效,导致父子关系无法建立。此时可通过 formId 属性实现页面级注册表兜底方案:
- 给
fs-form设置唯一的formId - 给每个
fs-form-item(或封装 wrapper)透传相同的formId
这样即使 relations 失效,也能通过页面级注册表找到对应的表单实例。
<fs-form formId="myForm" model="{{formModel}}" rules="{{formRules}}">
<form-item-wrapper formId="myForm" prop="name" label="姓名" />
<form-item-wrapper formId="myForm" prop="email" label="邮箱" />
</fs-form>8. Wrapper 封装场景(catchchange 防止重复事件)
在使用 wrapper 组件封装表单项内容组件(如 fs-form-file、fs-form-input 等)时,如果 wrapper 层需要自行处理变更逻辑并重新触发 change 事件,必须使用 catchchange 而非 bindchange 来监听子组件的变更。
问题原因
表单项内容组件的 change 事件默认开启了 bubbles: true 和 composed: true,以便 fs-form-item 能够监听到。如果使用 bindchange,事件会继续向上冒泡到达 fs-form-item;同时 wrapper 层又自行 triggerEvent('change', ...) 重新触发一个 change 事件,导致 fs-form-item 收到 2 次 change 事件,可能引发异常。
正确写法
<!-- 错误写法:会导致 fs-form-item 收到 2 次 change 事件 -->
<fs-form-file bindchange="onFileChange" />
<!-- 正确写法:使用 catchchange 阻止冒泡,由 wrapper 自行决定如何触发 -->
<fs-form-file catchchange="onFileChange" />// wrapper 组件
Component({
methods: {
onFileChange(e) {
// 处理文件变更逻辑
const newValue = e.detail.value;
// wrapper 自行决定何时触发变更事件,传递 bubbles: true 让 fs-form-item 能监听到
this.triggerEvent('change', { value: newValue }, { bubbles: true, composed: true });
}
}
});适用范围
此规则适用于所有表单项内容组件的 wrapper 封装场景,包括但不限于:
fs-form-filefs-form-inputfs-form-radiofs-form-checkboxfs-form-date
核心原则
wrapper 封装时,使用 catchchange 阻止子组件的 change 事件冒泡,由 wrapper 自行控制变更事件的触发时机和方式。
API
fs-form 属性
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|---|---|---|---|---|
| formId | 表单 ID,用于页面级注册表定位 | String | — | '' |
| model | 表单数据对象 | Object | — | {} |
| rules | 校验规则,key 为 prop | Object | — | {} |
| fieldAlign | 表单项整体布局方式 | String | left / top_and_bottom / center / whole_left | left |
fs-form 事件
| 事件名 | 说明 | 回调参数 |
|---|---|---|
| change | 表单字段变更时,事件开启了 bubbles: true 和 composed: true |
注意: 由于冒泡机制,一次字段变更会触发至少 2 次 change 事件,其中一次是字段本身的 change 事件,另一次是 form 的 change 事件。通过 type 可以区分 form 的 change 事件。
fs-form 方法
通过 selectComponent 获取实例后调用:
| 方法名 | 说明 | 返回值 |
|---|---|---|
| getValue() | 获取当前表单数据 | Object |
| validate() | 校验整个表单 | Promise<>,resolve 通过、reject 为校验失败 |
| clearValidate(props?) | 清空校验状态,不传则清空所有;传数组则清空指定 prop | void |
fs-form-item 属性
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|---|---|---|---|---|
| formId | 表单 ID,用于页面级注册表定位 | String | — | '' |
| prop | 对应 form model 的字段名 | String | — | '' |
| label | 标签文本 | String | — | '' |
| required | 是否必填(展示星号) | Boolean | — | false |
| fieldAlign | 当前项布局,覆盖 form 的 fieldAlign | String | left / top_and_bottom / center / whole_left | '' |
| rules | 当前项专属校验规则,优先于 form.rules[prop] | Array | 见下方「校验规则项」 | [] |
校验规则项(单条 rule)
与 Element UI / async-validator 对齐:
| 字段 | 说明 | 类型 |
|---|---|---|
| required | 是否必填 | Boolean |
| message | 校验失败提示 | String |
| pattern | 正则,字符串会转 RegExp | RegExp / String |
| min / max / len | 长度或数值限制,按 type 或值类型区分 | Number |
| whitespace | 为 true 时不允许纯空格 | Boolean |
| trigger | 触发时机:'blur' / 'change' / 'submit' 或数组 | String / Array |
| validator | 自定义校验,仅支持 Promise 写法:(rule, value, source, options) => Promise | Function |
