Skip to content

H5预览

APP下载

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是否显示必填星号booleantrue
showMessage是否显示错误信息booleantrue
disabled是否禁用整个表单booleanfalse
scrollToError滚动到第一个错误位置booleantrue

插槽

插槽名说明
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标签宽度stringnull
showAsterisk是否显示必填星号booleannull
showMessage是否显示错误信息booleannull
required是否必填booleanfalse

插槽

插槽名说明参数
default内容区域
error错误提示区域{error: string}

useForm

表单相关的钩子函数,便于快速获取和操作表单组件实例

ts
const { formRef, disabled, addField } = useForm();

返回值

参数说明类型
formRefcl-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>

返回值

参数说明类型
formItemRefcl-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,以便于后续操作。
  • 相关方法需在组件渲染完成后调用,建议在 onMountedonReady 等生命周期钩子中使用。

小贴士

当子组件结构较为复杂时,可以通过 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>