# Form 表单 
此组件一般用于表单场景,可以配置Input输入框,Select弹出框,进行表单验证等。
# 基本使用
此组件一般是用于表单验证使用,每一个表单域由一个un-form-item组成,表单域中可以放置un-input、un-checkbox、un-radio、un-switch等。
- 在表单组中,通过
model参数绑定一个对象,这个对象的属性为各个un-form-item内组件的对应变量。 - 由于表单验证和绑定表单规则时,需要通过
ref操作,故这里需要给form组件声明ref="formRef"属性。 - 关于
un-from-item内其他可能包含的诸如input、radio等组件,请见各自组件的相关文档说明。
注意
model 属性的数据类型是 UTSJSONObject 中响应式数据的绑定,需要使用 reactive 函数创建。不支持多级嵌套的响应式数据绑定。
v-model="formData.userInfo.name" 这种使用是错误的
<template> <view class="u-page"> <view class="u-demo-block"> <text class="u-demo-block__title">基础使用</text> <view class="u-demo-block__content"> <un-form labelPosition="left" :model="formData" :rules="formRules" ref="formRef" > <un-form-item label="姓名" prop="name" borderBottom > <un-input v-model="formData['name']" border="none" placeholder="请输入姓名" ></un-input> </un-form-item> <un-form-item label="性别" prop="sex" borderBottom @click="handleSexClick" > <un-input v-model="formData['sex']" disabled disabledColor="#ffffff" placeholder="请选择性别" border="none" ></un-input> <un-icon slot="right" name="arrow-right" ></un-icon> </un-form-item> <un-form-item label="水果" prop="radiovalue1" borderBottom > <un-radio-group v-model="formData['radiovalue1']"> <un-radio v-for="(item, index) in radiolist1" :key="index" :label="item.name" :name="item.name" ></un-radio> </un-radio-group> </un-form-item> <un-form-item label="兴趣爱好" prop="checkboxValue1" borderBottom labelWidth="80" > <un-checkbox-group v-model="formData['checkboxValue1']" shape="square" > <un-checkbox v-for="(item, index) in checkboxList1" :key="index" :label="item.name" :name="item.name" ></un-checkbox> </un-checkbox-group> </un-form-item> <un-form-item label="简介" prop="intro" borderBottom > <un-textarea placeholder="不低于3个字" v-model="formData['intro']" count ></un-textarea> </un-form-item> </un-form> <!-- 提交和重置按钮 --> <un-button type="primary" text="提交" customStyle="margin-top: 50px" @click="submit" ></un-button> <un-button type="error" text="重置" customStyle="margin-top: 10px" @click="reset" ></un-button> <un-action-sheet :show="showSex" :actions="actions" title="请选择性别" description="如果选择保密会报错" @close="showSex = false" @select="sexSelect" ></un-action-sheet> </view> </view> </view> </template> <script setup lang="ts"> import { ref, reactive } from 'vue' import type { UnValidateResult } from '@/uni_modules/uview-unix/components/un-form' import type { UnActionSheetAction, UnActionSheetSelectEvent } from '@/uni_modules/uview-unix/components/un-action-sheet' type RadioItem = { name: string; disabled: boolean; }; type CheckboxItem = { name: string; disabled: boolean; }; // 响应式数据定义 const showSex = ref<boolean>(false) // 表单模型 const formData = reactive({ name: 'uView UI', sex: '', radiovalue1: '苹果', checkboxValue1: [] as string[], intro: '', }) // 表单选项数据 const actions = ref<UnActionSheetAction[]>([ { name: '男' }, { name: '女' }, { name: '保密' }, ]) const radiolist1 = ref<RadioItem[]>([ { name: '苹果', disabled: false }, { name: '香蕉', disabled: false }, { name: '毒橙子', disabled: false }, ]) const checkboxList1 = ref<CheckboxItem[]>([ { name: '羽毛球', disabled: false }, { name: '跑步', disabled: false }, { name: '爬山', disabled: false }, ]) // 表单校验规则 const formRules = { name: [ { type: 'string', required: true, message: '请填写姓名', trigger: ['blur', 'change'], }, { // 同步验证示例 validator: (rule: any, value: string, callback: (message?: string) => void) => { if (value.length > 5) { return false // 返回false,验证不通过 } return true // 返回true,验证通过 }, message: '名字不能大于5个字符', trigger: ['change', 'blur'], }, { // 异步验证示例 validator: (rule: any, value: any, callback: (message?: string) => void) => { setTimeout(() => { if (!/^[\u4e00-\u9fa5]+$/.test(value.toString())) { callback('姓名必须为中文') } callback(null) //必须返回null }, 200) }, trigger: ['change', 'blur'], }, ], sex: { type: 'string', max: 1, required: true, message: () => { return '请选择性别' }, trigger: ['blur', 'change'], }, radiovalue1: { type: 'string', min: 1, max: 2, message: '橙子有毒', trigger: ['change'], }, checkboxValue1: { type: 'array', min: 2, required: true, message: '不能太宅,至少选两项', trigger: ['change'], }, intro: { type: 'string', min: 3, required: true, message: '简介不低于3个字', trigger: ['change'], }, } const formRef = ref<UnFormComponentPublicInstance | null>(null) /** * 处理性别点击事件 */ const handleSexClick = () => { showSex.value = true uni.hideKeyboard() } /** * 性别选择 */ const sexSelect = (action: UnActionSheetSelectEvent) => { formData['sex'] = action.item.name! showSex.value = false } /** * 表单提交 - 包含完整校验 */ const submit = () => { formRef.value?.validate().then((result: UnValidateResult) => { if (result.valid) { uni.showToast({ title: '校验通过', }) } else { uni.showToast({ title: result.errors[0].message, icon: 'none' }) } }) } /** * 表单重置 */ const reset = () => { formRef.value?.resetFields() } </script> <style lang="scss"> .u-page { background-color: #fff; } .u-demo-block__content { padding: 20rpx; } </style>✅ Copy success!
从上面的示例我们可以看到,rules中的属性名和form的属性名是一致的,同时传递给un-form-item的prop参数绑定的也是相同的属性名,注意这里prop参数绑定的是
字符串(属性名),而不是一个变量。
# Form-item组件说明
此组件一般需要搭配Form组件使用,也可以单独搭配Input等组件使用,由于此组件参数较多,这里只对其中参数最简要介绍,其余请见底部的API说明:
prop为传入Form组件的model中的属性字段,如果需要表单验证,此属性是必填的。labelPosition可以配置左侧"label"的对齐方式,可选为left和top。borderBottom是否显示表单域的下划线,如果给Input组件配置了边框,可以将此属性设置为false,从而隐藏默认的下划线。- 如果想在表单域配置左右的图标或小图片,可以通过
leftIcon和rightIcon参数实现。
# 验证规则
组件验证部分我们参考了async-validator (opens new window),一个字段可以设置多个内置规则,以及自定义规则,触发方式等, 每个字段的验证规则为一个数组,数组的每一个元素对象为其中一条规则(一个字段的验证可以配置多个规则),如下:
const rules = ref({ name: { type: 'string', required: true, message: '请填写姓名', trigger: ['blur', 'change'] }, code: { type: 'string', required: true, len: 4, message: '请填写4位验证码', trigger: ['blur'] }, sex: { type: 'string', max: 1, required: true, message: '请选择男或女', trigger: ['blur', 'change'] }, radiovalue1: { type: 'string', min: 1, max: 2, message: '生命是美好的,请不要放弃治疗', trigger: ['change'] }, checkboxValue1: { type: 'array', min: 2, required: true, message: '不能太宅,至少选两项', trigger: ['change'] }, intro: { type: 'string', min: 3, required: true, message: '不低于3个字', trigger: ['change'] }, hotel: { type: 'string', min: 2, required: true, message: '请选择住店时间', trigger: ['change'] }, birthday: { type: 'string', required: true, message: '请选择生日', trigger: ['change'] } })✅ Copy success!
# 验证规则属性
每一个验证规则中,可以配置多个属性,下面对常用的属性进行讲解,更具体的可以查看async-validator (opens new window)的文档说明:
trigger{string | Array}:触发校验的方式有2种:- change:字段值发生变化时校验
- blur:输入框失去焦点时触发
- 如果同时监听两种方式,需要写成数组形式:
['change', 'blur']
type{string}
内置校验规则,如这些规则无法满足需求,可以使用正则匹配、或者使用validator自定义方法并结合uView自带验证规则。- string:必须是
string类型,默认类型 - number:必须是
number类型 - boolean:必须是
boolean类型 - method:必须是
function类型 - regexp:必须是
regexp类型,这里的正则,指的是判断字段的内容是否一个正则表达式,而不是用这个正则去匹配字段值 - array:必须是
array类型 - object:必须是
object类型 - phone:必须是手机号格式
- url:必须是
url类型 - hex:必须是
16进制类型 - email:必须是
email类型 - any:任意类型
- string:必须是
required
布尔值,是否必填,配置此参数不会显示输入框左边的必填星号,如需要,请配置un-form-item的required为true,注意:如需在swiper标签内显示星号,需要给予swiper-item第一个根节点一定的margin样式pattern
要求此参数值为一个正则表达式,如: /\d+/,不能带引号,如:"/\d+/",组件会对字段进行正则判断,返回结果。min
最小值,如果字段类型为字符串和数组,会取字符串长度与数组长度(length)与min比较,如果字段是数值,则直接与min比较。max
最大值,规则同min参数len
指定长度,规则同min,优先级高于min和maxmessage
校验不通过时的提示信息validator{Function}:自定义同步校验函数,参数如下:rule:当前校验字段在 rules 中所对应的校验规则value:当前校验字段的值callback:校验完成时的回调,一般无需执行callback,返回true(校验通过)或者false(校验失败)即可
asyncValidator{Function}:自定义异步校验函数,参数如下:rule:当前校验字段在 rules 中所对应的校验规则value:当前校验字段的值callback:校验完成时的回调,执行完异步操作(比如向后端请求数据验证),如果不通过,需要callback(new Error('提示错误信息')),如果校验通过,执行callback()即可
# 综合实战
上面讲述了表单的规则和配置,以及uView内置规则的结合使用,下面我们进行一个综合 实战示例,要入对某一个字段进行如下验证(验证实现有多种方法,下方仅为引导示例,非唯一,或最优做法):
- 必填,同时可接受
change和blur触发校验:配置required参数为true,同时配置trigger为[change, blur] - 必须为字母或字符串,校验前先将字段值转为字符串类型:通过
pattern参数配置正则:/^[0-9a-zA-Z]*$/g,通过transform参数在校验前对字段值转换为字符串 - 长度6-8个字符之间:通过 配置
min为6,max为8 - 需要包含字母"A":使用uView的
uni.$u.test.contains()方法,并结合validator自定义函数实现 - 异步校验,输入完账号,输入框失去焦点时,向后端请求该账号是否已存在:通过上方的
asyncValidator异步函数进行验证。
综上,我们可以得出如下的一个配置规则(仅为综合演示,非最优做法):
rules: { name: [ // 必填规则 { required: true, message: '此为必填字段', // blur和change事件触发检验 trigger: ['blur', 'change'], }, // 正则判断为字母或数字 { pattern: /^[0-9a-zA-Z]*$/g, // 正则检验前先将值转为字符串 transform(value) { return string(value); }, message: '只能包含字母或数字' }, // 6-8个字符之间的判断 { min: 6, max: 8, message: '长度在6-8个字符之间' }, // 自定义规则判断是否包含字母"A" { validator: (rule, value, callback) => { return uni.$u.test.contains(value, "A"); }, message: '必须包含字母"A"' }, // 校验用户是否已存在 { asyncValidator: (rule, value, callback) => { uni.$u.http.post('/xxx/xxx', {name: value}).then(res => { // 如果验证不通过,需要在callback()抛出new Error('错误提示信息') if(res.error) { callback(new Error('姓名重复')); } else { // 如果校验通过,也要执行callback()回调 callback(); } }) }, // 如果是异步校验,无需写message属性,错误的信息通过Error抛出即可 // message: 'xxx' } ] }✅ Copy success!
# 校验错误提示方式
uView提供了多种校验的错误提示方式,传递给Form组件的errorType参数:
message:默认为输入框下方用文字进行提示none:不会进行任何提示border-bottom:配置作用域底部的下划线显示为红色,要求给form-item设置了borderBottom=true才有效toast:以"toast"提示的方式弹出错误信息,每次只弹出最前面的那个表单域的错误信息
<template> <un-form errorType="message"> ...... </un-form> </template>✅ Copy success!
# 校验
进行了上方的配置和讲解后,进入到最后一步,执行验证:
需要通过ref调用Form组件的validate方法,该方法返回一个Promise对象,包含校验结果。
<template> <view class="u-page"> <view class="u-demo-block"> <text class="u-demo-block__title">表单校验示例</text> <view class="u-demo-block__content"> <un-form :model="formData" ref="formRef" :rules="formRules"> <un-form-item label="姓名" prop="name" borderBottom> <un-input v-model="formData['name']" border="none" placeholder="请输入姓名"></un-input> </un-form-item> </un-form> <un-button type="primary" text="提交" customStyle="margin-top: 20px" @click="submit"></un-button> </view> </view> </view> </template> <script setup lang="ts"> import { ref, reactive } from 'vue' import type { UnValidateResult } from '@/uni_modules/uview-unix/components/un-form' // 表单模型 const formData = reactive({ name: '', }) // 表单校验规则 const formRules = { name: [ { type: 'string', required: true, message: '请输入姓名', trigger: ['blur', 'change'] } ] } const formRef = ref<UnFormComponentPublicInstance | null>(null) /** * 表单提交 */ const submit = () => { formRef.value?.validate().then((result: UnValidateResult) => { if (result.valid) { uni.showToast({ title: '校验通过', }) } else { uni.showToast({ title: result.errors[0].message, icon: 'none' }) } }) } </script> <style lang="scss"> .u-page { background-color: #fff; } .u-demo-block__content { padding: 20rpx; } </style>✅ Copy success!
# API
# Form Props
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|---|---|---|---|---|
| model | 表单数据对象 | UTSJSONObject | - | - |
| rules | 表单校验规则 | UTSJSONObject | - | - |
| errorType | 错误的提示方式,见上方说明 | string | message | none | toast | border-bottom | none |
| borderBottom | 是否显示表单域的下划线边框 | Boolean | true | - |
| labelPosition | 表单域提示文字的位置,left-左侧,top-上方 | string | left | top |
| labelWidth | 提示文字的宽度,单位px | string | number | 45 | 数值 / auto |
| labelAlign | lable字体的对齐方式 | string | left | center / right |
| labelStyle | lable的样式,对象形式 | UTSJSONObject | string | - | - |
# Form Methods
此方法如要通过ref手动调用
| 名称 | 说明 | 参数 |
|---|---|---|
| validate | 对整个表单进行校验的方法 | - |
| validateField | 对部分表单字段进行校验 | Function(value, Function(errorsRes)) |
| resetFields | 对整个表单进行重置,将所有字段值重置为初始值并移除校验结果 | - |
# Form-item Props
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|---|---|---|---|---|
| label | 左侧提示文字 | string | - | - |
| prop | 表单域model对象的属性名,在使用 validate、resetFields 方法的情况下,该属性是必填的 | string | - | - |
| rules | 表单校验规则 | UTSJSONObject | - | - |
| borderBottom | 是否显示下边框,如不需要下边框,需同时将un-form的同名参数设置为false | string | Boolean | true | true / false |
| labelWidth | 提示文字的宽度,单位rpx,如设置,将覆盖un-form的同名参数 | string | number | - | - |
| labelPosition | label的位置 | string | - | left / top |
| rightIcon | 右侧自定义字体图标(限uView内置图标)或图片地址 | string | - | - |
| leftIcon | 左侧自定义字体图标(限uView内置图标)或图片地址 | string | - | - |
| leftIconStyle | 左侧自定义字体图标的样式 | string | Object | - | - |
| required | 是否显示左边的"*"号,这里仅起展示作用,如需校验必填,请通过rules配置必填规则,如需在swiper标签内显示星号,需要给予swiper-item内第一个根节点一定的margin样式 | Boolean | false | true |
# Form-item Slot
| 名称 | 说明 |
|---|---|
| - | Form Item 的内容 |
| right | 右侧自定义内容,可以在此传入一个按钮,用于获取验证码等场景 |
| error | 自定义传入校验错误时显示的信息,通过作用域插槽暴露了内部当前message错误信息 |
# Form-item Events
| 事件名 | 说明 | 回调参数 | 版本 |
|---|---|---|---|
| click | 点击时触发 | - | - |
# 数据类型
Form组件导出了以下数据类型,用于表单校验结果的类型安全处理:
| 类型名称 | 说明 | 属性 | 类型 | 描述 |
|---|---|---|---|---|
| UnValidateError | 校验错误信息类型 | field | string | 字段名称 |
message | string | 错误提示信息 | ||
| UnValidateResult | 表单校验结果类型 | valid | boolean | 校验是否通过 |
errors | UnValidateError[] | 错误信息列表 |
/** * 校验错误信息类型 * 用于表示单个字段的校验错误 */ type UnValidateError = { field: string; // 字段名 message: string; // 错误消息 } /** * 表单校验结果类型 * 用于表示整个表单的校验结果 */ type UnValidateResult = { valid: boolean; // 校验是否通过 errors: UnValidateError[]; // 错误信息列表 }✅ Copy success!