核心概念解析:节点、属性、验证规则与错误对象

说实话,很多同学刚开始接触 FormalNode 时,最头疼的就是这几个概念傻傻分不清。我当年带团队做表单验证重构时,也踩过不少坑。今天咱们就把这四个核心概念彻底掰开揉碎,讲明白。

一、节点(Node)—— 验证的最小单元

节点是什么?说白了,它就是你要验证的「那个东西」。可以是一个输入框,也可以是一组数据,甚至是一个复杂的对象。

核心理解:节点是验证逻辑的载体,每个节点都包含自己的属性、验证规则和错误信息。

我在项目中遇到过这样的情况:有人把整个表单当做一个节点去验证,结果错误定位变得一团糟。正确的做法是——每个独立的数据项都应该是一个节点。

// 节点示例
const node = {
  id: 'username',
  value: '张三',
  props: { required: true, minLength: 2 },
  rules: ['required', 'minLength:2'],
  errors: []
};

你想想看,如果用户名和密码混在一个节点里,那错误提示该显示在哪个字段旁边?嗯,这就是节点设计的意义所在。

二、属性(Props)—— 节点的配置清单

属性就是节点的「说明书」。它告诉验证引擎:这个节点有什么要求、该怎么验证、错误时怎么显示。

属性名 类型 说明
required boolean 是否必填
minLength number 最小长度
maxLength number 最大长度
pattern RegExp 正则匹配
custom function 自定义验证

我个人习惯把 props 分成两类:声明式属性函数式属性。声明式的比如 required、minLength,直接写值就行。函数式的比如 custom,需要传一个验证函数。

小技巧:属性名尽量保持语义化,别用 a、b、c 这种缩写。我见过一个项目,属性名全是拼音首字母,维护起来简直噩梦。

三、验证规则(Rules)—— 验证的执行逻辑

规则就是「怎么验证」。它是一组函数的集合,每个函数接收节点的值,返回验证结果。

为什么会需要单独的规则层?直接写在 props 里不行吗?嗯,这里要注意:规则是可复用的验证逻辑,而属性是节点的配置。同一个规则可以用在不同节点上,只是配置参数不同。

// 规则定义
const rules = {
  required: (value) => {
    if (value === '' || value === null || value === undefined) {
      return { valid: false, message: '此项不能为空' };
    }
    return { valid: true };
  },
  
  minLength: (value, min) => {
    if (value.length < min) {
      return { valid: false, message: `最少需要${min}个字符` };
    }
    return { valid: true };
  }
};

我曾经踩过一个坑:把验证规则直接写在组件里,结果每个页面都要重写一遍。后来抽成公共规则库,维护成本直接降了 60%。

四、错误对象(Error Object)—— 验证结果的载体

错误对象就是验证后的「成绩单」。它告诉你:哪个节点错了、错在哪里、怎么提示用户。

标准错误对象结构:

{
  nodeId: 'username',      // 哪个节点
  rule: 'required',        // 哪条规则
  message: '用户名不能为空', // 错误提示
  value: '',               // 当时的输入值
  timestamp: 1700000000000 // 验证时间
}

我个人建议错误对象一定要包含 nodeIdrule 两个字段。为什么?因为定位问题的时候,你不仅要知道哪个字段错了,还要知道是哪条规则触发的。不然排查起来就像大海捞针。

注意:错误对象不要存太多冗余信息。我见过有人把整个节点数据都塞进错误对象里,结果一个表单验证下来,错误对象比表单数据还大。保持精简,够用就行。

五、四者关系全景图

这四个概念的关系,我用一张图来展示:

节点 (Node) 验证的最小单元 属性 (Props) 节点的配置清单 验证规则 (Rules) 验证的执行逻辑 错误对象 验证结果的载体 包含 引用 生成 关联 FormalNode 核心概念关系图

从图上可以看得很清楚:节点包含属性,属性引用规则,规则生成错误对象,错误对象又关联回节点。这是一个闭环,缺一不可。

六、实战中的最佳实践

说了这么多理论,来点实际的。我在项目中总结了几条经验:

  1. 节点粒度要细:一个输入框一个节点,别偷懒合并。否则错误定位会变得很痛苦。
  2. 属性尽量声明式:能用 required: true 就别写个函数。声明式更直观,也更容易维护。
  3. 规则要原子化:每条规则只做一件事。比如「必填」和「长度校验」分开写,别揉在一起。
  4. 错误对象要标准化:团队统一错误对象结构,前端展示和后端日志都能复用。

我的习惯:每次新建一个表单,先花 5 分钟把节点和属性定义好。磨刀不误砍柴工,后面写验证规则会顺畅很多。

嗯,这四个概念就讲到这里。记住一句话:节点是骨架,属性是血肉,规则是灵魂,错误对象是反馈。把这四个概念吃透了,FormalNode 的验证体系你就掌握了八成。

专注资料整理