校验系统
校验系统主要由字段模型承载,Form 提供批量入口。字段负责声明规则、执行自身校验并维护反馈;Form 的 validate() / submit() 会聚合字段树中的数据字段,再批量调度校验。
大部分的校验能力都依赖于 @silver-formily/validator,也可以阅读 validator 的快速上手章节作为参考。
校验器
字段通过 validator 描述校验规则。
字符串格式
字符串会被当成 format,是格式规则的简写:
field.validator = 'email' // 等价于 { format: 'email' }
field.validator = 'url'内置格式之外,也可以通过 registerValidateFormats 注册自定义格式。
函数校验
函数可以返回字符串、布尔值或反馈对象:
field.validator = (value) => {
return value ? '' : '不能为空'
}
field.validator = {
validator: value => value.length > 3,
message: '至少 3 个字符',
}
field.validator = (value) => {
return {
type: 'warning',
message: value?.endsWith('@company.com') ? '' : '建议填写公司邮箱',
}
}对象规则
对象结构可以表达更完整的校验约束:
field.validator = {
required: true,
format: 'email',
minLength: 3,
maxLength: 20,
message: '格式不正确',
}也可以通过 registerValidateRules 注册自定义规则。
规则数组
数组用于组合多条规则。不同写法最终都会被归一成规则数组:
field.validator = [
'email',
{ required: true },
value => value ? '' : '不能为空',
]
field.validator = [
{ format: 'email' },
{ required: true },
{ validator: value => value ? '' : '不能为空' },
]校验时机
规则对象可以通过 triggerType 控制触发时机:
| triggerType | 触发时机 |
|---|---|
onInput | 输入时,默认值 |
onBlur | 失焦时 |
onFocus | 聚焦时 |
field.validator = [
{ required: true },
{ format: 'email', triggerType: 'onBlur' },
]这些字段方法会触发对应时机的校验:
field.onInput('silver')
field.onFocus()
field.onBlur()手动调用 field.validate() 时可以指定触发类型;不指定则校验全部规则:
await field.validate()
await field.validate('onBlur')校验策略
validateFirst 用于控制是否在首条规则失败后停止继续校验。
form.createField({
name: 'username',
validateFirst: true,
validator: [
{ required: true },
{ minLength: 3 },
],
})默认为 false,即使某条规则失败,也会继续执行后续规则并返回完整反馈。
校验状态
字段通过 validated 区分“当前没有错误”和“已经实际校验通过”:
field.valid
field.validated
field.validateStatusvalid 初始即为 true,只表示字段当前没有错误。validated 仅在至少一条与当前触发类型匹配的规则执行完成后为 true。字段值变化、开始下一次匹配规则的校验或重置后,validated 会恢复为 false。
普通规则校验通过时,validateStatus 为 success;校验失败、存在警告或正在校验时分别为 error、warning、validating。没有规则或当前触发类型没有匹配规则时,validateStatus 保持 undefined。
普通校验通过不会自动写入成功反馈,因此 selfSuccesses 和 form.successes 仍为空。如需显示成功文案,需要由校验器显式返回 { type: 'success', message }。
校验反馈
校验结果存放在字段的 feedbacks 中。字段自身保存的是 IFieldFeedback,不包含路径信息:
interface IFieldFeedback {
triggerType?: 'onInput' | 'onFocus' | 'onBlur'
type?: 'error' | 'success' | 'warning'
code?: 'ValidateError' | 'ValidateSuccess' | 'ValidateWarning'
| 'EffectError' | 'EffectSuccess' | 'EffectWarning'
messages?: any[]
}Form 或父字段聚合反馈时,会在 IFieldFeedback 上补充可选的 path 和 address,形成 IFormFeedback。
字段提供了按类型聚合的便捷属性:
field.feedbacks
field.errors
field.warnings
field.successes
field.selfErrors
field.selfWarnings
field.selfSuccessesself 前缀只读取字段自身反馈;非 self 属性会聚合自身和所有子孙字段的反馈。
写入反馈
业务副作用也可以直接写入反馈:
field.selfErrors = ['用户名已存在']
field.selfWarnings = ['建议使用公司邮箱']
field.selfSuccesses = ['校验通过']也可以调用 setSelfErrors()、setSelfWarnings() 和 setSelfSuccesses()。这些写法产生的反馈会使用 Effect* code,以便和校验器产生的 Validate* code 分离。errors、warnings、successes 是包含子孙字段的只读聚合结果,不能用来写入反馈。
也可以查询反馈:
field.queryFeedbacks({ type: 'error' })
field.queryFeedbacks({ code: 'ValidateError' })
field.queryFeedbacks({ address: 'username' })Form 级校验
Form 提供批量校验入口:
await form.validate()
await form.submit(async (values) => {
await request(values)
})form.validate() 会聚合字段树中的数据字段并调度字段校验;form.submit() 会先校验,再把表单值交给提交回调。
form.errors
form.warnings
form.successes
form.valid想自行注册校验规则或需要多语言的支持请参考 FormValidatorRegistry API。