Form 表单验证
表单组件用于数据录入与校验,支持多种校验规则、错误提示、禁用状态等功能。
提示
表单的 disabled
禁用状态会影响包括以下组件:(自定义组件可以使用 useForm
去获取表单的禁用状态)
- cl-input(输入框)
- cl-input-number(数字输入框)
- cl-checkbox(复选框)
- cl-radio(单选框)
- cl-rate(评分)
- cl-textarea(文本域)
- cl-select(选择器)
- cl-select-date(日期选择器)
- cl-select-time(时间选择器)
- cl-cascader(级联选择器)
- cl-switch(开关)
- cl-upload(上传)
- cl-slider(滑块)
cl-form
参数
参数 | 说明 | 类型 | 可选值 | 默认值 |
---|---|---|---|---|
pt | 样式穿透配置 | PassThrough | — | — |
modelValue | 表单数据模型 | any | — | {} |
rules | 表单规则 | Map<string, ClFormRule[]> | — | [] |
labelPosition | 标签位置 | ClFormLabelPosition | 'top' | 'left' | 'right' | 'top' |
labelWidth | 标签宽度 | string | — | '120rpx' |
showAsterisk | 是否显示必填星号 | boolean | — | true |
showMessage | 是否显示错误信息 | boolean | — | true |
disabled | 是否禁用整个表单 | boolean | — | false |
scrollToError | 滚动到第一个错误位置 | boolean | — | true |
插槽
插槽名 | 说明 |
---|---|
default | 内容区域 |
方法
方法名 | 说明 | 参数 |
---|---|---|
addField | 添加某个验证字段 | (prop: string) => void |
removeField | 移除某个验证字段 | (prop: string) => void |
getValue | 获取指定字段的表单值 | (prop: string) => any | null |
setError | 设置指定字段的错误提示 | (prop: string, error: string) => void |
getError | 获取指定字段的错误提示 | (prop: string) => string |
getErrors | 获得错误信息,并滚动到第一个错误位置 | () => Promise<ClFormValidateError[]> |
removeError | 移除指定字段的错误提示 | (prop: string) => void |
clearErrors | 清空所有错误提示 | () => void |
getRule | 获取指定字段的规则 | (prop: string) => ClFormRule[] |
setRule | 设置字段规则 | (prop: string, rules: ClFormRule[]) => void |
removeRule | 移除字段规则 | (prop: string) => void |
validateRule | 验证指定字段的规则 | (value: any | null, rule: ClFormRule) => string | null |
clearValidate | 清空所有字段的验证 | () => void |
validateField | 验证指定字段 | (prop: string) => string | null |
validate | 验证所有字段 | (callback: (valid: boolean, errors: ClFormValidateError[]) => void) => Promise<void> |
cl-form-item
cl-form-item
参数优先级高于cl-form
参数
参数 | 说明 | 类型 | 可选值 | 默认值 |
---|---|---|---|---|
pt | 样式穿透配置 | PassThrough | — | — |
label | 字段标签 | string | — | '' |
prop | 字段名称 | string | — | '' |
rules | 验证规则 | ClFormRule | — | [] |
labelPosition | 标签位置 | ClFormLabelPosition | 'top' | 'left' | 'right' | null |
labelWidth | 标签宽度 | string | — | null |
showAsterisk | 是否显示必填星号 | boolean | — | null |
showMessage | 是否显示错误信息 | boolean | — | null |
required | 是否必填 | boolean | — | false |
插槽
插槽名 | 说明 | 参数 |
---|---|---|
default | 内容区域 | |
error | 错误提示区域 | {error: string} |
useForm
表单相关的钩子函数,便于快速获取和操作表单组件实例
ts
const { formRef, disabled, addField } = useForm();
返回值
参数 | 说明 | 类型 |
---|---|---|
formRef | cl-form 组件实例 | ClFormComponentPublicInstance |
disabled | 表单是否禁用 | boolean |
addField | 添加某个验证字段 | (prop: string) => void |
removeField | 移除某个验证字段 | (prop: string) => void |
getValue | 获取指定字段的表单值 | (prop: string) => any | null |
setError | 设置指定字段的错误提示 | (prop: string, error: string) => void |
getError | 获取指定字段的错误提示 | (prop: string) => string |
getErrors | 获得错误信息,并滚动到第一个错误位置 | () => Promise<ClFormValidateError[]> |
removeError | 移除指定字段的错误提示 | (prop: string) => void |
clearErrors | 清空所有错误提示 | () => void |
getRule | 获取指定字段的规则 | (prop: string) => ClFormRule[] |
setRule | 设置字段规则 | (prop: string, rules: ClFormRule[]) => void |
removeRule | 移除字段规则 | (prop: string) => void |
validateRule | 验证指定字段的规则 | (value: any | null, rule: ClFormRule) => string | null |
clearValidate | 清空所有字段的验证 | () => void |
validateField | 验证指定字段 | (prop: string) => string | null |
validate | 验证所有字段 | (callback: (valid: boolean, errors: ClFormValidateError[]) => void) => Promise<void> |
isError | 检查字段是否存在错误 | (prop: string) => boolean |
useFormItem
表单项的钩子函数,用于获取当前表单项的状态。
ts
const { isError } = useFormItem();
示例
当需要根据表单字段验证结果为 input
组件添加红色边框样式时:
重要
- 需要将
input
组件放置在cl-form-item
组件内部 isError
状态仅在表单配置了验证规则时生效
vue
<template>
<cl-form-item prop="name">
<input :class="{ 'border-red-500': isError }"></input>
</cl-form-item>
</template>
<script setup lang="ts">
import { useFormItem } from "@/uni_modules/cool-ui";
const { isError } = useFormItem();
</script>
返回值
参数 | 说明 | 类型 |
---|---|---|
formItemRef | cl-form-item 组件实例 | ClFormComponentPublicInstance |
isError | 字段是否存在错误 | boolean |
验证规则
参数
参数 | 说明 | 类型 |
---|---|---|
required | 是否必填 | boolean |
message | 错误提示 | string |
min | 最小值、最小位数 | number |
max | 最大值、最大位数 | number |
pattern | 正则表达式 | RegExp |
validator | 自定义验证 | (value: any) => string | true |
是否必填
在此处添加 required
并不意味着该字段为必填项,实际是否必填需在 cl-form-item
组件中通过 required
属性进行配置。
ts
const rules = new Map<string, ClFormRule[]>([
[
"nickName",
[
{ required: true, message: t("用户名不能为空") },
]
]
]
字符数长度
ts
const rules = new Map<string, ClFormRule[]>([
[
"nickName",
[
{ min: 3, max: 20, message: t("用户名长度在3-20个字符之间") }
]
]
]
正则表达式
ts
const rules = new Map<string, ClFormRule[]>([
[
"email",
[
{ pattern: /^[^\s@]+@[^\s@]+\.[^\s@]+$/, message: t("邮箱格式不正确") }
]
]
]
最大最小值
当 height
字段为数字 number 类型时
ts
const rules = new Map<string, ClFormRule[]>([
[
"height",
[
{ min: 160, max: 190, message: t("身高在160-190cm之间") }
]
]
]
数组长度
当 tags
字段为数组 Array 类型时
ts
const rules = new Map<string, ClFormRule[]>([
[
"tags",
[
{ min: 1, max: 2, message: t("标签最多选择2个") }
]
],
]
自定义验证
- 返回
true
表示验证通过,返回字符串则作为验证失败时的提示信息。 - 注意:此时
value
的类型为any
,如需进行字符串或数组等类型的操作,可通过as string
等方式进行类型断言。
ts
const rules = new Map<string, ClFormRule[]>([
[
"birthday",
[
{
validator(value) {
if (dayUts(value).isAfter(dayUts("2010-01-01"))) {
return t("出生年月不大于2010-01-01");
}
return true;
}
}
]
]
]
动态字段验证
- 请注意,
prop
的格式应为contacts[0].phone
,也支持更深层级的写法,如contacts[0].info.users[0].name
。 - 另外,
rules
必须为数组格式,并且需要显式声明类型为as ClFormRule[]
。
vue
<template>
<cl-form-item :label="t('动态验证')" required prop="contacts">
<view
class="contacts border border-solid border-surface-200 rounded-xl p-3 dark:!border-surface-700"
>
<cl-form-item
v-for="(item, index) in formData.contacts"
:key="index"
:label="t('联系人') + ` - ${index + 1}`"
:prop="`contacts[${index}].phone`"
:rules="
[
{
required: true,
message: t('手机号不能为空')
}
] as ClFormRule[]
"
required
>
<view class="flex flex-row items-center">
<cl-input
:pt="{
className: 'flex-1 mr-2',
}"
v-model="item.phone"
:placeholder="t('请输入手机号')"
></cl-input>
<cl-button
type="light"
icon="subtract-line"
@tap="removeContact(index)"
></cl-button>
</view>
</cl-form-item>
<cl-button icon="add-line" @tap="addContact">{{
t("添加联系人")
}}</cl-button>
</view>
</cl-form-item>
</template>
<script lang="ts" setup>
type FormData = {
// ...
contacts: Contact[];
};
const formData = ref<FormData>({
// ...
contacts: [],
}) as Ref<FormData>;
// 添加一个联系人
function addContact() {
formData.value.contacts.push({
phone: "",
});
}
// 移除联系人
function removeContact(index: number) {
formData.value.contacts.splice(index, 1);
}
</script>
更多规则参考 /pages/demo/form/form.uvue
中的写法
类型定义
ts
// 表单规则类型
type ClFormRule = {
// 是否必填
required?: boolean;
// 错误信息
message?: string;
// 最小长度
min?: number;
// 最大长度
max?: number;
// 正则验证
pattern?: RegExp;
// 自定义验证函数
validator?: (value: any | null) => boolean | string;
};
type ClFormValidateError = {
field: string;
message: string;
};
type ClFormValidateResult = {
valid: boolean;
errors: ClFormValidateError[];
};
type ClFormLabelPosition = "left" | "top" | "right";
示例
简单用法
formData
的类型定义参考如下写法:先自定义类型(类型名如FormData
可自定义),再通过ref
并结合as
明确类型。formData
必须使用ref
定义,不能用reactive
。
vue
<template>
<cl-form v-model="formData">
<cl-form-item prop="avatarUrl">
<cl-upload v-model="formData.avatarUrl" test></cl-upload>
</cl-form-item>
<cl-form-item label="用户名" prop="nickName">
<cl-input
v-model="formData.nickName"
placeholder="请输入用户名"
clearable
></cl-input>
</cl-form-item>
</cl-form>
</template>
<script setup lang="ts">
import { ref, type Ref } from "vue";
// 自定义表单数据类型
type FormData = {
avatarUrl: string;
nickName: string;
};
// 表单数据
const formData = ref<FormData>({
avatarUrl: "",
nickName: "神仙都没用",
}) as Ref<FormData>;
</script>
添加验证规则
- 通过为
cl-form
组件配置rules
属性,可以为表单项添加校验规则。 - 可通过
cl-form-item
组件的required
参数,快速指定字段为必填项。 rules
必须定义为new Map<string, ClFormRule[]>
,这样才能获得类型提示和类型校验。- 注意:
rules
的默认值应为二维数组的形式。
vue
<template>
<cl-form v-model="formData" :rules="rules">
<cl-form-item prop="avatarUrl">
<cl-upload v-model="formData.avatarUrl" test></cl-upload>
</cl-form-item>
<cl-form-item label="用户名" prop="nickName" required>
<cl-input
v-model="formData.nickName"
placeholder="请输入用户名"
clearable
></cl-input>
</cl-form-item>
</cl-form>
</template>
<script setup lang="ts">
import { ref, type Ref } from "vue";
import { type ClFormRule } from "@/uni_modules/cool-ui";
// 自定义表单数据类型
type FormData = {
avatarUrl: string;
nickName: string;
};
// 表单数据
const formData = ref<FormData>({
avatarUrl: "",
nickName: "神仙都没用",
}) as Ref<FormData>;
// ------ 以下为新增内容 ------
// 表单验证规则
const rules = new Map<string, ClFormRule[]>([
[
"nickName",
[
{ required: true, message: t("用户名不能为空") },
{ min: 3, max: 20, message: t("用户名长度在3-20个字符之间") },
],
],
]);
</script>
调用组件事件
cl-form
组件的ref
命名必须为formRef
,以便于后续操作。- 相关方法需在组件渲染完成后调用,建议在
onMounted
或onReady
等生命周期钩子中使用。
小贴士
当子组件结构较为复杂时,可以通过 useForm
钩子获取上级表单组件实例,便于进行字段校验、获取或清除错误信息等操作。
vue
<template>
<cl-form ref="formRef" v-model="formData" :rules="rules">
<cl-form-item prop="avatarUrl">
<cl-upload v-model="formData.avatarUrl" test></cl-upload>
</cl-form-item>
<cl-form-item label="用户名" prop="nickName" required>
<cl-input
v-model="formData.nickName"
placeholder="请输入用户名"
clearable
></cl-input>
</cl-form-item>
</cl-form>
</template>
<script setup lang="ts">
import { ref, type Ref } from "vue";
import { type ClFormRule, useForm } from "@/uni_modules/cool-ui";
// 自定义表单数据类型
type FormData = {
avatarUrl: string;
nickName: string;
};
// 表单数据
const formData = ref<FormData>({
avatarUrl: "",
nickName: "神仙都没用",
}) as Ref<FormData>;
// ------ 以下为新增内容 ------
// 表单验证规则
const rules = new Map<string, ClFormRule[]>([
[
"nickName",
[
{ required: true, message: t("用户名不能为空") },
{ min: 3, max: 20, message: t("用户名长度在3-20个字符之间") },
],
],
]);
// 获取 cl-form 的组件实例
const { formRef, validate, clearValidate } = useForm();
// 重置表单数据
function reset() {
formData.value.avatarUrl = "";
formData.value.nickName = "";
// 清空验证
clearValidate();
}
// 提交表单,调用表单验证方法 validate
function submit() {
validate((valid, errors) => {
if (valid) {
// 验证通过
} else {
// 验证不通过,可以提示错误信息 errors
}
});
}
</script>