不只校验手机号:我的鸿蒙开源校验库,开始处理更复杂的表单场景

0 阅读7分钟

不只校验手机号:我的鸿蒙开源校验库,开始处理更复杂的表单场景

做鸿蒙应用时,表单校验看起来是小事:判断一下必填,再检查手机号格式,好像就够了。

但业务稍微复杂一点,就会遇到另一批问题:

  • 新建页面要求资料完整,编辑页面却只提交修改的字段,规则要写两份吗?
  • 切换个人和企业身份后,必填字段变了,关联错误怎么更新?
  • 用户名查重还没返回,用户已经改了输入甚至退出页面,旧任务怎么办?
  • 后端给了一份 JSON Schema,里面有当前不支持的规则,能不能明确告诉开发者?

我一直在维护的鸿蒙 ArkTS 开源校验库 @hmkit/validator,最近完成了 1.2.0。这次想分享的,不是一长串 API,而是这些实际场景背后的改进。

发布进度:1.2.0 已提供 GitHub Release,OHPM 发布提交已成功,审核上架状态以 OHPM 页面为准。下文新增能力对应 1.2.0。

先用几行代码认识它

@hmkit/validator 是一个零依赖、纯 ArkTS 实现的声明式表单和数据校验库,采用 MIT 协议开源。

最简单的使用方式,是把分散的判断写成一条规则:

import { v } from '@hmkit/validator';

const result = v.string()
  .required('请输入手机号')
  .phone()
  .validate('13800138000');

// result.valid 为 true

除了单个字段,也可以统一描述一组数据:

import { v } from '@hmkit/validator';

const schema = v.object({
  'name': v.string().required('请输入姓名').min(2),
  'phone': v.string().required().phone(),
  'age': v.number().required().integer().min(18, '需年满 18 岁'),
});

const data: Record<string, Object> = {
  'name': '张三',
  'phone': '123',
  'age': 16,
};

const result = schema.validate(data);
for (const error of result.errors) {
  console.error(`${error.path}: ${error.message}`);
}

已有能力还包括中国本地化规则、嵌套对象和数组、跨字段与异步校验、中英文错误消息、字段标签、错误码,以及 ArkUI 表单控制器。

这里也提醒一句:身份证校验位、银行卡 Luhn 等规则属于格式或校验算法检查,不等于实名认证、账户有效性或银行鉴权。

1. 编辑资料,不必重新维护整套规则

新建资料时,我们通常要求字段完整;编辑资料时,可能只更新其中一部分。

如果数据只有一层,可以手动把字段设为可选。但遇到嵌套地址、列表、树形结构,以及不同身份对应不同字段的联合模型,维护成本就会明显增加。

这次我重点完善了 deepPartial():从已有 Schema 派生深层局部更新模型,保留原始模型,扩展到递归 Lazy、组合结构和判别联合等场景。

其中一个容易忽略的细节是判别字段。比如通过 kind 区分个人资料和企业资料,即使允许局部更新,也仍然需要知道本次数据属于哪个分支。新的处理会保留这个检查,缺少或传入未知判别值不会直接放行。

这项能力不是“把所有规则都取消”:

  • 字段可省略,不代表可以传 null。
  • 业务自定义的 refine / transform 回调不会被自动改写。
  • 支持递归 Schema,不等于支持输入对象自身的循环引用。
  • 校验局部更新不会自动合并业务数据;合并后仍应使用完整模型再次校验。

我希望它减少规则重复,同时让数据边界保持清楚。

2. JSON Schema 导入,不支持的规则应该看得见

在配置化表单或前后端共享约束的场景中,JSON Schema 很有用。但“能导入”不代表其中每个关键词都被正确执行了。

1.2.0 增加了导入诊断和严格模式。例如,当前还不支持 multipleOf,可以先检查:

import { inspectJSONSchema } from '@hmkit/validator/interop';

const source = JSON.parse(
  '{"type":"number","multipleOf":2}'
) as Record<string, Object>;

const diagnostics = inspectJSONSchema(source);
// 诊断会指出 #/multipleOf 当前未支持

导入时可以通过 strict: true 拒绝包含诊断项的 Schema;也可以保持默认宽松模式,通过 onDiagnostic 收集问题。

这一版还补充了布尔 Schema,并修复了 oneOf 分支重叠、组合与同级约束同时存在时的处理,以及部分字符串和数值边界。

需要说清楚:这里的严格模式是当前实现的能力预检,不是完整 JSON Schema 标准合规认证,也不承诺所有文档都能无损往返转换。完整支持范围和限制写在仓库文档里。

3. 异步校验,除了“等结果”,还要能结束任务

远程查重的难点,往往不是发请求,而是如何处理请求的生命周期。

页面退出了,要不要继续等?批量校验几十条数据,是否应该限制并发?某个任务一直没有响应,后面的数据还要继续排队吗?

这次围绕这些问题补充了:

  • 异步批量校验的并发上限与超时控制。
  • 取消令牌的订阅与退订。
  • 自定义字符串、数字异步规则对本次上下文及取消通知的访问。
  • 异常、超时与取消路径上的资源清理。

超时会通知本次调用的子令牌,不会直接取消调用者共享的父令牌;父令牌取消时,则可以通知对应调用。

不过,取消通知不会凭空终止底层网络请求。业务适配器仍需要响应通知,调用自己的停止请求方法。页面也需要管理外部任务的令牌,不能只调用 FormValidator.dispose() 就认为所有网络请求都结束了。

仓库里提供了可编译的请求模拟示例,方便先理解这套生命周期,再接入真实网络。

4. 能力继续增加,但入口尽量保持清楚

项目扩展后,我也在关注另一个问题:只需要基础校验的使用者,不应该为了找一个 API,先理解全部高级功能。

目前保留兼容的主入口,同时提供 lite、18 个独立规则子路径,以及这些功能入口:

  • @hmkit/validator/composition:组合相关能力。
  • @hmkit/validator/interop:Schema 互操作相关能力。
  • @hmkit/validator/execution:执行策略与取消相关能力。
  • @hmkit/validator/form:表单控制器相关能力。

除了使用已有规则,也可以通过自定义同步/异步规则、插件和扩展接口适配业务需求。

这里不做“按需导入就一定缩小多少包体”的承诺:完整 HAR 本次约 146 KiB,随功能增加有所增长。按需入口提供更明确的依赖选择,最终应用包体收益仍需在具体工程中测量。

这次做了哪些验证?

新增功能之外,也修复了嵌套校验上下文丢失、对象覆盖后的可选标记残留,以及表单销毁后仍派发依赖校验等问题。

发布前的本地验证结果是:

  • 263 项测试全部通过。
  • 行覆盖率 92.83%,函数覆盖率 82.67%,分支覆盖率 83.86%。
  • 公共 API、按需入口、包元数据和安全检查通过。
  • 主入口与按需入口的独立 HAR 消费工程均构建通过。

模拟器上,两个入口也分别完成了三次进程重启、重复执行、取消状态恢复和退出重进验证。

测试边界同样公开:模拟器首次启动曾出现一次生命周期超时,后续重复测试未复现,根因尚未确定;真机和真实网络场景尚未完成验收。263 项是本地测试数量,不是“263 项真机测试”,覆盖率也不代表没有缺陷。

详细结果保留在验证报告中,方便大家评估是否适合自己的项目。

欢迎试用,也欢迎带着真实场景来提需求

如果你正在做鸿蒙注册登录、资料编辑、嵌套数据校验,或需要把校验规则从页面逻辑里抽出来,可以看看这个项目。

1.2.0 审核上架后,可在项目中安装指定版本:

ohpm install @hmkit/validator@1.2.0

若暂时提示版本不存在,请先查看 OHPM 审核上架状态;也可以从 GitHub Release 获取本次 HAR。

如果觉得有帮助,欢迎 Star。更欢迎带着具体输入、预期结果和最小复现来提 Issue 或 PR。

后续我会继续围绕真实业务完善它:规则能复用,错误能定位,异步任务能管理,扩展时也能保留清晰的边界。

你在鸿蒙开发中遇到过哪些难维护的校验场景?欢迎在评论区聊聊。