uni-app 中复杂表单校验需手动管理时机、字段注册与跨字段依赖,rules 键名须与 model 顶层字段名完全一致,不支持嵌套路径,动态字段须用 addrule/removerule 手动维护唯一 key,validator 必须显式处理空值并返回 promise,跨字段联动推荐 watch + validatefield。

复杂表单校验在 uni-app 里没法靠 rules 配置一劳永逸,必须手动控制校验时机、字段注册和跨字段依赖——否则你看到的“不生效”“提示错位”“新增项没校验”,基本都是规则没对上或状态没清理。
rules 键名必须和 model 顶层字段名完全一致
这是 80% 校验失败的根源。uni-forms 不解析嵌套路径,model: { user: { phone: '' } } + rules: { 'user.phone': [] } 是无效的。
- model 必须是扁平结构,例如
{ phone: '', email: '' } -
rules的 key 必须严格匹配,比如{ phone: { rules: [...] } } -
<uni-forms-item name="phone"></uni-forms-item>中的name也得是"phone",不能是"user.phone"或变量表达式 - 如果业务数据天然嵌套,用计算属性或
watch同步出扁平字段,别硬套点号路径
validator 函数必须显式判空并返回 Promise
确认密码、结束时间 ≥ 开始时间、用户名查重这些逻辑,不能只写 pattern,必须用 validator。但直接抄示例容易漏掉两个关键点:
- 空值不会自动跳过:即使字段设了
required: true,validator仍会被调用,需手动判断if (!value) return true或返回错误消息 - 异步校验(如查重)必须返回
Promise,并在resolve/reject前调用callback(),否则校验卡住无响应 - 函数内访问其他字段值,不要依赖
this(this是undefined),改用闭包捕获formDataRef,或通过data参数取当前完整表单数据 - 正则务必加
^和$,/1[3-9]\d{9}/会误判"abc13812345678def";正确写法是/^1[3-9]\d{9}$/
v-for 动态字段必须用 addRule/removeRule 手动管理
uni-forms 不监听数组变化,v-for 渲染的子项不会自动注册进校验系统。push/splice 后,旧规则残留、新字段无校验、提示错位是常态。
- 每次新增一项,立刻调用
formRef.value.addRule('field_123456789', rules),key 必须唯一(建议用Date.now()或索引+时间戳拼接) - 删除前,先
formRef.value.removeRule('field_123456789'),再从model数组中splice - 绝对不要用数组
index当 rule key —— 重排后 key 错位,校验就乱套 - 批量操作后调用
formRef.value.clearValidate(),清空缓存状态,避免旧错误提示残留
跨字段联动校验要用 validateField + watch
比如密码确认实时比对、结束时间 ≥ 开始时间,这类强依赖场景不能只靠单字段 validator,得主动触发关联字段校验。
- 在
passwordConfirm的validator里,别直接读model.password(可能是旧值),应设trigger: 'change'并在函数内取最新值 - 多个字段强关联时,建议统一收口到一个自定义校验函数,手动调用
formRef.value.validateField(['start', 'end']) - 日期类比较注意时区,用
new Date(value).getTime()比字符串比对更可靠 - 实时联动推荐用
watch监听依赖字段变化,然后调用validateField,而不是等用户失焦才校验
最易被忽略的是:动态字段的 rule key 唯一性、异步 validator 中 callback 的调用时机、以及跨字段校验时对最新值的获取方式——这三个点一旦出错,调试时几乎看不到报错,只有“看起来没反应”。











