暗黑模式
Form 表单 1.0.13
手机扫码预览
23:59
组件名:rice-form
表单组件用于数据校验,支持异步校验。1.0.13
版本开始支持。
平台兼容性
uni-app x
Android | iOS | 鸿蒙Next | 微信小程序 | h5 |
---|---|---|---|---|
√ | √ | √ | √ | √ |
验证规则
Form
组件提供了表单验证规则,只需为 rules
属性传入约定的验证规则,并将 FormItem
的 name
属性设置为需要验证的特殊键值即可。
- 在
Form
组件上通过rules
定义表单校验规则,注意rules为 Map<string, FormRules[]> 类型; FormRules数据结构见下; - 在
FormItem
组件上通过rules
定义表单项校验规则,注意rules为 FormRules[] 类型; rules
可统一配置在Form
上,也可单独定义在FormItem
上,最终所有规则会自动合并;Form
组件上的model
为表单数据对象,可以是UTSJSONObject
类型,也可以是自定义type类型,如
ts
//UTSJSONObject <rice-form :model="form1"/>
const form1=ref({
username: '',
password: '',
})
//自定义type <rice-form :model="form2"/>
type Form2 = {
username : string,
password : string
}
const form2 = ref<Form2>({
username: '',
password: '',
})
是否必填
- 可以在
FormItem
上 设置required
为true
,此时默认的错误提示message 为必填项
,如果需要自定义message
,请通过rules
设置必填。
ts
// 在 Form 上使用,注意写在Form上面的为 Map 类型; 也可以使用 ref 响应式数据进行定义 ref<Map<string,FormRules[]>>(...)
const rules = new Map<string, FormRules[]>([
[
"username",
[{ required: true, message: '请输入用户名',trigger: 'blur' }]
],
[
"password",
[{required: true, message: '请输入密码'}]
]
])
// 在 FormItem 上使用,注意写在Form上面的为 FormRules[] 类型
const usernameRules = ref<FormRules[]>([{ required: true, message: '请输入用户名',trigger: 'blur'}])
最大值和最小值/长度
当值为数字类型时,比较的是数字的大小;当值为字符串/数组时,比较的是字符串/数组的长度
ts
// 在 Form 上使用,注意写在Form上面的为 Map 类型
const rules = new Map<string, FormRules[]>([
[
"username",
[{ min: 3, max: 10, message: '字数需为 3 至 10 位'}]
]
])
// 在 FormItem 上使用,注意写在Form上面的为 FormRules[] 类型
const usernameRules = ref<FormRules[]>([{ min: 3, max: 10, message: '字数需为 3 至 10 位'}])
通过 pattern 进行正则校验
通过正则表达式进行校验,正则无法匹配表示校验不通过
ts
// 在 Form 上使用,注意写在Form上面的为 Map 类型
const rules = new Map<string, FormRules[]>([
[
"phone",
[{ pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号', trigger: 'all' }]
],
])
通过 validator 进行函数校验
通过函数进行校验,返回true
表示校验通过,返回false
或字符串表示校验不通过,其中字符串即为错误提示。
注意:value
的类型为 any
,如需使用特定数据类型的方法,需要使用 as
进行类型断言
ts
//密码的校验函数
const passwordValidator = (value : any | null) => {
const val = value as string
if (val.length < 6) return '密码的长度不能小于6位'
if (val.startsWith('123456')) return '密码开头不能为连续的123456'
//只有返回 true 才表示校验通过
return true
}
// 在 Form 上使用,注意写在Form上面的为 Map 类型
const rules = new Map<string, FormRules[]>([
[
"password",
[{ validator: passwordValidator }]
]
])
通过 validator 进行异步函数校验
可以返回一个 Promise
来进行异步校验
ts
//异步校验函数,直接返回一个 Promise 对象 示例
const usernameAsyncValidator = (value : any | null) => {
return new Promise<boolean | string>((resolve) => {
setTimeout(() => {
//只有返回 true 才表示校验通过
resolve(value == '123' ? true : '请输入123')
}, 500)
})
}
// 模拟网络请求
const sleep = (value : string) => {
return new Promise<boolean>((resolve) => {
setTimeout(() => {
resolve(value == '123456')
}, 1500)
})
}
//异步校验函数 使用 async/await 示例
const passwordAsyncValidator = async (value : any | null) => {
const res = await sleep(value as string)
return res
}
//异步校验函数
const rules = new Map<string, FormRules[]>([
[
"username",
[{ validator: usernameAsyncValidator, trigger: 'blur' }]
],
[
"password",
[{ validator: passwordAsyncValidator, trigger: 'blur', message: '请输入123456' }]
],
])
基础用法
vue
<template>
<rice-form :model="form1" :rules="rules1" ref="formRef1" label-width="100px" class="demo-form">
<rice-form-item name="username" label="用户名">
<rice-input v-model="form1['username']" placeholder="请输入用户名" border="none" :custom-style="inputStyle" />
</rice-form-item>
<rice-form-item name="phone" label="手机号" show-required>
<rice-input v-model="form1['phone']" placeholder="请输入手机号" border="none" type="number"
:custom-style="inputStyle" />
</rice-form-item>
<rice-form-item name="password" label="密码" required :rules="passwordRules">
<rice-input v-model="form1['password']" placeholder="请输入密码" border="none" type="password"
:custom-style="inputStyle" />
</rice-form-item>
</rice-form>
<view class="flex">
<rice-button type="primary" text="提 交" class="btn" shape="round" @click="submit1" />
<rice-button type="success" text="只校验密码" class="btn" shape="round" :custom-style="{marginLeft:'12px'}"
@click="checkPassword" />
</view>
<text class="reset-text" @click="clearAllValidate">点我清除校验结果</text>
</template>
ts
import { FormRules, FormValidateErrors } from "@/uni_modules/rice-ui"
const form1 = ref({
username: '',
phone: '',
password: '',
})
//密码的校验函数
const passwordValidator = (value : any | null) => {
const val = value as string
if (val.length < 6) return '密码的长度不能小于6位'
if (val.startsWith('123456')) return '密码开头不能为连续的123456'
//只有返回 true 才表示校验通过
return true
}
//rules 校验规则,注意写在Form上面的为 Map 类型
const rules1 = new Map<string, FormRules[]>([
[
"username",
[
{ required: true, message: '请输入用户名' },
{ min: 3, max: 10, message: '字数需为 3 至 10 位', trigger: 'blur' },
]
],
[
"phone",
//正则校验
[{ pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号', trigger: 'all' }]
],
[
"password",
[
//函数校验
{ validator: passwordValidator },
//正则校验
{ pattern: /[a-zA-Z].*\d|\d.*[a-zA-Z]/, message: '密码需要包含字母和数字' },
]
]
])
//写在formItem上的rules
const passwordRules = ref<FormRules[]>([{ max: 12, message: '密码的长度不能大于12位' }])
const formRef1 = ref<RiceFormComponentPublicInstance | null>(null)
const submit1 = async () => {
const result = await formRef1.value!.validate()
//校验成功
if (result == true) {
showToast('校验成功')
} else {
//校验失败,返回校验失败的数组集合
const errsName = (result as FormValidateErrors[]).map(v => v.name)
console.log('校验失败的name合集', errsName)
}
}
//只校验密码
const checkPassword = async () => {
const result = await formRef1.value!.validateFields(['password'])
const errMsg = result == true
? '密码校验成功'
: '密码校验失败:' + (result as FormValidateErrors[])[0].message
showToast(errMsg)
}
// 清除校验结果
const clearAllValidate = () => {
formRef1.value!.clearAllValidate()
//清除指定字段的校验信息可调用以下方法
// formRef1.value!.clearValidate(['username','password'])
}
//自定义 rice-input 的样式
const inputStyle = ref({
height: '24px',
padding: '0px',
backgroundColor: 'transparent',
})
scss
.demo-form {
background-color: var(--demo-block-color);
padding: 0 16px;
}
.btn {
flex: 1;
}
.flex {
flex-direction: row;
flex-wrap: wrap;
background-color: var(--demo-block-color);
padding: 16px;
}
.reset-text {
background-color: var(--demo-block-color);
text-align: right;
font-size: 12px;
color: var(--demo-text-color-2);
padding-bottom: 12px;
padding-right: 18px;
/* #ifdef WEB */
cursor: pointer;
/* #endif */
}
异步校验
vue
<template>
<rice-form :model="form2" :rules="rules2" ref="formRef2" label-width="100px" class="demo-form">
<rice-form-item name="username" label="用户名">
<rice-input v-model="form2.username" placeholder="输入123才校验成功" border="none" :custom-style="inputStyle" />
</rice-form-item>
<rice-form-item name="password" label="密码">
<rice-input v-model="form2.password" placeholder="输入123456才校验成功" border="none" :custom-style="inputStyle" />
</rice-form-item>
</rice-form>
<view class="flex">
<rice-button type="primary" text="提 交" class="btn" shape="round" @click="submit2" />
</view>
</template>
ts
import { FormRules, FormValidateErrors } from "@/uni_modules/rice-ui"
type Form2 = {
username : string,
password : string
}
const form2 = ref<Form2>({
username: '',
password: '',
})
//异步校验函数,直接返回一个 Promise 对象 示例
const usernameAsyncValidator = (value : any | null) => {
return new Promise<boolean | string>((resolve) => {
setTimeout(() => {
//只有返回 true 才表示校验通过
resolve(value == '123' ? true : '请输入123')
}, 500)
})
}
// 模拟异步操作
const sleep = (value : string) => {
return new Promise<boolean>((resolve) => {
setTimeout(() => {
resolve(value == '123456')
}, 1500)
})
}
//异步校验函数 使用 async/await 示例
const passwordAsyncValidator = async (value : any | null) => {
const res = await sleep(value as string)
return res
}
//异步校验函数
const rules2 = new Map<string, FormRules[]>([
[
"username",
[
{ required: true, message: '请输入用户名', trigger: 'blur' },
{ validator: usernameAsyncValidator, trigger: 'blur' },
]
],
[
"password",
[{ validator: passwordAsyncValidator, trigger: 'blur', message: '请输入123456' }]
],
])
const formRef2 = ref<RiceFormComponentPublicInstance | null>(null)
const submit2 = async () => {
uni.showLoading({
title: '校验中…',
mask: true
})
const result = await formRef2.value!.validate()
uni.hideLoading()
//校验成功
if (result == true) {
showToast('校验成功')
} else {
//校验失败,返回校验失败的数组集合
const errs = (result as FormValidateErrors[]).map(v => `${v.label}:${v.message}`).join('/')
showToast(errs)
}
}
//自定义 rice-input 的样式
const inputStyle = ref({
height: '24px',
padding: '0px',
backgroundColor: 'transparent',
})
自定义样式
required-position
可以设置必填符号的位置,支持left
和right
;error-bottom
可以设置校验未通过时下边框是否描红,仅border-bottom
为true
时生效;label-style
可以设置标签的颜色大小等样式;content-style
可以设置FormItem
内容区域的样式;error-style
可以设置错误提示区域的样式,如文字样式大小等样式,如想要此区域与label左对齐,设置{marginLeft:0}
即可;
vue
<template>
<rice-form :model="form3" label-width="100px" required-position="right" error-bottom
:label-style="{fontSize:'26rpx'}" :error-style="{'text-align':'right'}" :disabled="formStatus=='disabled'"
:readonly="formStatus=='readonly'" ref="formRef3" class="demo-form">
<rice-form-item label="用户名" name="username" required>
<rice-input v-model="form3.username" placeholder="请输入用户名" border="none" :custom-style="inputStyle"
input-align="right" />
</rice-form-item>
<rice-form-item label="生日" name="birthday" required suffix-icon="arrow-down" @click="showDatePicker=true">
<rice-input v-model="form3.birthday" placeholder="请选择生日" border="none" :custom-style="inputStyle" readonly
input-align="right" />
</rice-form-item>
<rice-form-item label="性别" name="gender" required :rules="genderRules"
:content-style="{'align-items':'flex-end'}">
<rice-radio-group v-model="form3.gender" direction="row">
<rice-radio value="man" label="男" />
<rice-radio value="woman" label="女" />
<rice-radio value="unknow" label="保密" />
</rice-radio-group>
</rice-form-item>
</rice-form>
<view class="flex">
<rice-button type="primary" text="提 交" class="btn" shape="round" @click="submit3" />
</view>
<!-- 日期选择 -->
<rice-datetime-picker v-model:show="showDatePicker" min-date="1900-01-01" max-date="2025-12-01"
model-value="2000-01-01" title="选择生日" @confirm="onDateConfirm" />
</template>
ts
import { FormRules, FormValidateErrors } from "@/uni_modules/rice-ui"
type Form3 = {
username : string,
birthday : string,
gender : 'man' | 'woman'
}
const form3 = ref<Form3>({
username: '',
birthday: '',
gender: 'man'
})
const formStatus = ref('normal')
const genderValidator = (value : any | null) => {
if (value == 'unknow') return '未知的性别'
return true
}
const genderRules = ref<FormRules[]>([{ validator: genderValidator }])
const formRef3 = ref<RiceFormComponentPublicInstance | null>(null)
const submit3 = async () => {
const result = await formRef3.value!.validate()
//校验成功
if (result == true) {
showToast('校验成功')
} else {
showToast('校验未通过')
//校验失败,返回校验失败的数组集合
const errsName = (result as FormValidateErrors[]).map(v => v.name)
console.log('校验失败的name合集', errsName)
}
}
//选择日期
const showDatePicker = ref(false)
const onDateConfirm = (val : string) => {
form3.value.birthday = val
}
//自定义 rice-input 的样式
const inputStyle = ref({
height: '24px',
padding: '0px',
backgroundColor: 'transparent',
})
自定义插槽
支持 label
,error
, suffix
插槽
vue
<template>
<rice-form :model="form4" ref="formRef4" class="demo-form" label-position="top">
<rice-form-item name="username" :content-style="{'flex-direction':'row'}" required :border-bottom="false">
<template #label>
<view class="slot-label">
<text class="slot-label__text">用户名</text>
<rice-icon name="info" />
</view>
</template>
<input v-model="form4.username" placeholder="请输入用户名" class="form-input" />
<template #error="{message}">
<view class="error-slot">
<rice-icon name="info" color="#ee0a24" size="14px" />
<text class="error-slot__text">用户名校验失败:{{message}}</text>
</view>
</template>
<template #suffix>
<rice-icon name="user" size="18px" :custom-style="{'margin-left':'10px'}" />
</template>
</rice-form-item>
</rice-form>
<view class="flex">
<rice-button type="primary" text="提 交" class="btn" shape="round" @click="submit4" />
</view>
</template>
ts
import { FormRules, FormValidateErrors } from "@/uni_modules/rice-ui"
type Form4 = {
username : string,
password : string,
}
const form4 = ref<Form4>({
username: "",
password: "",
})
const formRef4 = ref<RiceFormComponentPublicInstance | null>(null)
const submit4 = async () => {
const result = await formRef4.value!.validate()
//校验成功
if (result == true) {
showToast('校验成功')
} else {
showToast('校验未通过')
//校验失败,返回校验失败的数组集合
const errsName = (result as FormValidateErrors[]).map(v => v.name)
console.log('校验失败的name合集', errsName)
}
}
//自定义 rice-input 的样式
const inputStyle = ref({
height: '24px',
padding: '0px',
backgroundColor: 'transparent',
})
scss
.demo-form {
background-color: var(--demo-block-color);
padding: 0 16px;
}
.btn {
flex: 1;
}
.flex {
flex-direction: row;
flex-wrap: wrap;
background-color: var(--demo-block-color);
padding: 16px;
}
.reset-text {
background-color: var(--demo-block-color);
text-align: right;
font-size: 12px;
color: var(--demo-text-color-2);
padding-bottom: 12px;
padding-right: 18px;
/* #ifdef WEB */
cursor: pointer;
/* #endif */
}
.form-input {
flex: 1;
background-color: var(--demo-block-color-6);
color: var(--demo-text-color);
border-radius: 8px;
height: 40px;
font-size: 15px;
padding: 0 12px;
}
.error-slot {
flex-direction: row;
&__text {
color: var(--rice-form-error-color);
font-size: 12px;
margin-left: 4px;
}
}
.slot-label {
flex-direction: row;
&__text {
color: var(--demo-text-color);
font-size: 15px;
margin-right: 4px;
}
}
不显示错误信息
设置 show-error
为 false
即可不显示错误信息
vue
<template>
<rice-form :model="form5" :show-error="false" ref="formRef5" label-width="100px" class="demo-form">
<rice-form-item name="username" label="用户名" required>
<rice-input v-model="form5['username']" placeholder="请输入用户名" border="none" :custom-style="inputStyle" />
</rice-form-item>
</rice-form>
<view class="flex">
<rice-button type="primary" text="提 交" class="btn" shape="round" @click="submit5" />
</view>
</template>
ts
const form5 = ref({
username: ''
})
const formRef5 = ref<RiceFormComponentPublicInstance | null>(null)
const submit5 = async () => {
const result = await formRef5.value!.validate()
//校验成功
if (result == true) {
showToast('校验成功')
} else {
//校验失败,返回校验失败的数组集合
const errs = (result as FormValidateErrors[]).map(v => `${v.label}:${v.message}`).join('/')
showToast(errs)
}
}
//自定义 rice-input 的样式
const inputStyle = ref({
height: '24px',
padding: '0px',
backgroundColor: 'transparent',
})
表单状态
info 表单的 disabled
和 readonly
状态会影响以下组件:rice-checkbox 复选框
、rice-input 输入框
、rice-radio 单选框
、rice-rate 评分
、rice-slider 滑块
、rice-stepper 步进器
、rice-switch 开关
、rice-textarea 多行文本框
API
Form Props
属性名 | 类型 | 说明 | 默认值 |
---|---|---|---|
model | UTSJSONObject/自定义type类型(只能为对象类型) | 表单数据对象 | - |
rules | Map<string, FormRules[]> | 表单校验规则,注意为 Map 类型。FormRules数据格式见下 | - |
label-width | String|Number | 标签的宽度 | auto |
label-position | String | 标签的位置,默认 left ,可选 right top | left |
label-style | UTSJSONObject | 自定义标签style,如文字大小和颜色 | - |
show-required | Boolean | 是否显示必填的符号,默认根据rules规则显示;只是页面显示效果,不会进行空值的校验 | - |
required-position | String | 必填符号的位置,默认 left ,可选 right | left |
show-error | Boolean | 校验失败时是否显示错误信息 | true |
border-bottom | Boolean | 是否显示表单域的下划线边框 | true |
error-bottom | Boolean | 校验未通过时下边框是否标红,border-bottom 为 true 时生效 | false |
scroll-to-error | Boolean | 是否自动滚动到第一个校验不通过的字段,APP端需在 scroll-view 或 list-view 组件中使用才有效,当前仅APP端支持 | false |
disabled | Boolean | 是否禁用此表单中的所有组件,支持的组件见上 | false |
readonly | Boolean | 是否只读此表单中的所有组件,支持的组件见上 | false |
error-style | UTSJSONObject | 错误信息区域的自定style样式 | - |
custom-style | UTSJSONObject | 自定style样式 | - |
FormItem Props
属性名 | 类型 | 说明 | 默认值 |
---|---|---|---|
name | String | 表单域model 对象的属性名 | - |
label | String | 标签文字 | - |
label-width | String|Number | 标签的宽度,会覆盖 Form 中的 label-width | auto |
label-position | String | 标签的位置,默认 left ,可选 right top ,会覆盖 Form 中的 label-position | left |
label-style | UTSJSONObject | 自定义标签style,如文字大小和颜色,会和 Form 中的 label-style 进行合并 | - |
rules | FormRules[] | 表单项的校验规则,会与 Form 中同名(name 值一致)的校验规则自动合并,注意为 FormRules[] 类型。FormRules数据格式见下 | - |
required | Boolean | 是否必填,为 true 时会对表单项进行空值的校验 | false |
show-required | Boolean | 是否显示必填的符号,默认根据rules规则显示;只是页面显示效果,不会进行空值的校验 | - |
required-position | String | 必填符号的位置,默认 left ,可选 right | left |
show-error | Boolean | 校验失败时是否显示错误信息 | true |
border-bottom | Boolean | 是否显示表单域的下划线边框 | true |
error-bottom | Boolean | 校验未通过时下边框是否标红,border-bottom 为 true 时生效 | false |
suffix-icon | String | 尾部 Icon 的name值 | - |
suffix-icon-style | UTSJSONObject | 尾部 Icon 的style样式 | - |
content-style | UTSJSONObject | 默认区域内的自定样式 | - |
error-style | UTSJSONObject | 错误信息区域的自定style样式,会和 Form 中的 error-style 进行合并 | - |
custom-style | UTSJSONObject | 自定style样式 | - |
Form 方法
通过 ref 可以获取到 Form
实例并且调用实例的方法
方法名 | 说明 | 参数 | 返回值 |
---|---|---|---|
validate | 验证所有表单项 | - | Promise<boolean | FormValidateErrors[]> , 返回 true 时表示校验通过,校验不通过时会返回未通过的表单项合集,FormValidateErrors格式见下 |
validateFields | 验证指定的表单项 | 要校验表单项的name值合集, 如 validateFields(['name','age']) | 同 validate 方法的返回值 |
clearAllValidate | 清除表单全部的校验信息 | - | - |
clearValidate | 清除表单指定字段的校验信息 | 要清除表单项的name值合集, 如 clearValidate(['name','age']) | - |
scrollToField | 滚动到指定的字段位置,当前仅 App 端支持 | 要滚动到某个字段的name值,如 scrollToField('name') | - |
调用方法示例
ts
const formRef = ref<RiceFormComponentPublicInstance | null>(null)
//需确保formRef.value不为null的情况下才能使用 "!."
formRef1.value!.validate()
FormItem Event
事件名 | 说明 | 回调参数 |
---|---|---|
click | formItem的点击事件 | - |
clickContent | 内容区域的点击事件 | - |
clickSuffix | 尾部icon区域的点击事件 | - |
Form Slots 插槽
名称 | 说明 | 参数 |
---|---|---|
default | 默认内容区域 | - |
FormItem Slots 插槽
名称 | 说明 | 参数 |
---|---|---|
label | 标签区域 | - |
suffix | 尾部区域 | - |
error | 错误信息区域 | (message : string) |
FormRules 数据结构
rules 属性定义的校验规则属性如下:
键名 | 说明 | 类型 |
---|---|---|
required | 是否为必选字段,当值为空值时(空字符串、空数组、空对象、undefined、null ),校验不通过 | Boolean |
message | 校验未通过时的错误信息 | String |
trigger | 本项规则的触发时机,默认 change ,可选值为 blur all | FormTrigger |
min | 最小值/长度,当值为数字类型时,比较的是数字的大小;当值为字符串/数组时,比较的是字符串/数组的长度 | Number |
max | 最大值/长度,比较方式同 min | Number |
pattern | 通过正则表达式进行校验,正则无法匹配表示校验不通过 | RegExp |
validator | 通过函数进行校验,返回true 表示校验通过,返回false 或字符串表示校验不通过;可以返回一个 Promise 来进行异步校验 | (value : any | null) => (boolean | string) | Promise<boolean | string> |
FormValidateErrors 数据结构
表单校验不通过时返回的表单项合集属性如下:
键名 | 说明 | 类型 |
---|---|---|
name | 表单域model 对象的属性名 | String |
rule | 当前未通过的rule | FormRules |
message | 校验未通过时的错误信息 | String |
label | 标签文字 | String|Null |
类型定义
Form 组件导出如下类型:
ts
//标签的位置
type FormLabelPosition = 'left' | 'top' | 'right'
//必填符号的位置
type FormRequiredPosition = 'left' | 'right'
//规则的触发时机
type FormTrigger = 'change' | 'blur' | 'all'
//rule 规则类型
type FormRules = {
required ?: boolean,
message ?: string,
trigger ?: FormTrigger,
min ?: number,
max ?: number,
pattern ?: RegExp,
validator ?: (value : any | null) => (boolean | string) | Promise<boolean | string>,
}
//校验不通过时的表单项合集
type FormValidateErrors = {
name : string,
rule : FormRules,
message : string,
label ?: string,
}
//Form 组件类型
const formRef = ref<RiceFormComponentPublicInstance | null>(null)
FormItem 组件导出如下类型:
ts
//FormItem 组件类型
const formItemRef = ref<RiceFormItemComponentPublicInstance | null>(null)