1 api描述
/**
* @title useForm
* @description composition api useForm
* @params useFormOptions: UseFormOptions<T>
* @return { form: UnwrapNestedRefs<T> (reactive); valid: (key?: keyof T) => boolean }
*/
- 入参:useFormOptions
- 返回值:{form, valid}
2 api调用方式
import useForm from '@/use/useForm'
interface LoginForm {
phone: string
password: string
verifyCode: string
}
const { form, valid } = useForm<LoginForm>({
// 1. 可以设置字段校验规则(以[field]: {$value, $valid?, $invalidCbk?}形式)
// 2. 也可以不设置校验规则(以[field]: value形式);不设置校验规则的化后续valid校验函数校验该字段会直接返回true
phone: {
$value: '',
$valid: (val) => telRegex.test(val),
$inValidCbk: () => Toast('手机号格式不正确')
},
password: '',
verifyCode: {
$value: '',
$valid: (val) => !!val,
$inValidCbk: () => Toast('请填写验证码')
}
})
// -------------- 看看效果 -------------------
console.log(form) // reactive({phone: '', password:'', verifyCode: ''})
// 1. valid函数支持传入一个或多个表单字段名作为参数,并对这些字段按照前面预设规则进行校验
valid('phone') // false
form.phone = '13111111111'
valid('phone') // true
valid('phone', 'password') // true
// 2. valid函数不传参数默认校验form中的所有字段
valid() // false; Toast('请填写验证码');
3 api function源码
import { reactive } from 'vue-demi'
type Form = Record<string, any>
interface ValidatorType<T> {
$value: T
$valid?: (value: T) => boolean
$inValidCbk?: (value: T) => void
}
type UseFormOptions<T extends Form> = { [K in keyof T]: ValidatorType<T[K]> | T[K] }
export default function useForm<T extends Form>(useFormOptions: UseFormOptions<T>) {
const rawForm: any = {};
Object.entries(useFormOptions).forEach(([key, val]) => {
rawForm[key as keyof T] = val?.$value ?? val
})
const form = reactive<T>(rawForm)
const valid = (...keys: Array<keyof T>): boolean => {
const validatorFcn = <K extends keyof T>(key: K, validator: ValidatorType<T[K]>) => {
const { $valid, $inValidCbk } = validator || {}
if (!$valid) return true
const isValid = $valid(form[key])
if (!isValid) { $inValidCbk?.(form[key]) }
return isValid
}
if (keys) {
return keys.every(key => {
const validator = useFormOptions[key]
return validatorFcn(key, validator)
})
}
return Object.entries(useFormOptions).every(([key, validator]) => validatorFcn(key, validator))
}
return { form, valid }
}
实现难度不大,流程入下:
- 对传入的useFormOptions提取出form表单项内容;
- valid校验函数通过Array.every()函数对传入的每个字段进行规则校验,所有字段校验通过则返回true,有字段校验不通过则调用该字段前面预设的$inValidCbk函数。