airi 中的 Vue 响应式表单校验:useAsyncValidator 声明式校验实战指南

原创2026-10-15 20:08:481,957 阅读
文章标签:AI 应用大模型AI Agent数字人前端后端桌面应用移动开发音频

airi 中的 Vue 响应式表单校验:useAsyncValidator 声明式校验实战指南

useAsyncValidator 是 VueUse @Integrations 系列中封装 async-validator(Ant Design Vue / Element Plus 表单校验同款引擎)的响应式组合式函数,它把「校验数据 + 校验规则」直接绑定进 Vue 的响应式系统,让表单校验状态(是否通过、错误信息、错误字段)无需手写订阅即可自动更新。在 airi 仓库中,它被收录于 .agents/skills/vueuse-functions 技能库(对应官方 VueUse v14.4.0),供 Vue 3 / Nuxt 3 项目按需接入。读完本文,你将掌握 useAsyncValidator 的安装方式、选项与返回值语义、声明式规则写法,以及如何用它替代手写校验逻辑。

useAsyncValidator 是什么

useAsyncValidator 是 async-validator 的响应式包装器(Wrapper)。async-validator 本身是一个纯函数式、面向 descriptor(描述符)的异步校验库:你定义一组规则(Rules),它针对某个数据对象执行校验,返回错误列表。VueUse 将其包装后,实现了两点关键增强:

  • 响应式联动:校验对象 value 与校验规则 rules 都可以是 ref / getter / 普通对象,任一变化都会触发重新校验;
  • 结果状态化:校验结果(pass、errors、errorFields 等)以 ShallowRef / ComputedRef 暴露,可直接用于模板渲染与逻辑判断。

在 airi 的 vueuse-functions 技能体系中,该函数被归类为 @Integrations(第三方库集成)类别,调用规则为 EXTERNAL:只有项目已安装 async-validator 时才使用,不应作为默认依赖自动引入(见 SKILL.md)。

安装 async-validator

由于 useAsyncValidator 属于 @vueuse/integrations 包,而 async-validator 是它的可选 peer 依赖,使用时需要显式安装:

npm i async-validator@^4

在 pnpm workspace 的 airi 仓库中,这一依赖关系同样有据可查:pnpm-lock.yaml 显示 @vueuse/integrations@14.4.0 的 peerDependencies 声明了 async-validator: ^4,且标记为 optional(peerDependenciesMeta.async-validator.optional: true),意味着 @vueuse/integrations 本身可选装,只有实际使用 useAsyncValidator 时才需要补装 async-validator@^4(pnpm-lock.yaml)。若使用 pnpm,可直接:

pnpm add @vueuse/integrations async-validator@^4

基本用法与导入

在 Vue 3 组件(或 Nuxt 3)中导入:

import { useAsyncValidator } from '@vueuse/integrations/useAsyncValidator'

注意导入路径来自 @vueuse/integrations 子路径,而非 @vueuse/core。函数签名如下:

export declare function useAsyncValidator(
  value: MaybeRefOrGetter<Record<string, any>>,   // 待校验数据
  rules: MaybeRefOrGetter<Rules>,                 // async-validator 规则描述符
  options?: UseAsyncValidatorOptions,             // 可选配置
): UseAsyncValidatorReturn & PromiseLike<UseAsyncValidatorReturn>
  • value:校验目标,类型为 Record<string, any>,支持传入普通对象、ref 或 getter(MaybeRefOrGetter);
  • rules:async-validator 的规则对象,同样支持响应式传入;
  • 返回值同时实现了 PromiseLike,因此可以 await useAsyncValidator(...) 直接获取结果。

最小可用示例

import { reactive } from 'vue'
import { useAsyncValidator } from '@vueuse/integrations/useAsyncValidator'

const form = reactive({ username: '', email: '' })

const { pass, errors, errorFields } = useAsyncValidator(form, {
  username: { required: true, message: '用户名不能为空' },
  email:   { type: 'email', message: '邮箱格式不正确' },
})

默认情况下(immediate: true、manual: false),首次调用即触发校验,此后 form.username / form.email 一旦变化,校验会自动重新执行,pass、errors 等状态同步更新——无需手动监听数据。

选项配置详解

UseAsyncValidatorOptions 共三个字段,控制校验的触发时机:

选项 类型 默认值 说明
validateOption ValidateOption 无 透传给 async-validator 的底层校验选项
immediate boolean true 是否立即触发首次校验;仅在 manual 未开启时生效
manual boolean false 设为 true 后,关闭自动校验,只能手动调用 execute()

manual + execute 手动触发模式

当需要「提交时才校验」(典型如登录表单、保存按钮)时:

const { execute, pass, errorInfo } = useAsyncValidator(
  form,
  rules,
  { immediate: false, manual: true },
)

// 提交按钮
async function onSubmit() {
  const result = await execute()
  if (!result.pass) {
    console.log(result.errorInfo)
    return
  }
  // 校验通过,继续提交
}

manual: true 与 immediate 的组合需要留意:immediate 只在 manual 未开启时生效,因此手动模式下 immediate 的设置会被忽略。

validateOption 透传

validateOption 会原样转发给 async-validator 的 validate() 方法(官方称为 ValidateOption),典型用途包括 first(遇首个错误即停止)与 firstFields(按字段遇错即停),用于控制错误上报粒度。文档源码中以 @see 形式指向 async-validator 官方 options 说明(见 useAsyncValidator.md),实际可用的字段以所安装的 async-validator@^4 版本为准。

返回值语义与类型声明

useAsyncValidator 返回 UseAsyncValidatorReturn & PromiseLike<UseAsyncValidatorReturn>,其中 UseAsyncValidatorReturn 与单次执行的 UseAsyncValidatorExecuteReturn 结构如下(完整类型见 useAsyncValidator.md):

export type AsyncValidatorError = Error & {
  errors: ValidateError[]               // 全部错误数组
  fields: Record<string, ValidateError[]> // 按字段分组
}

export interface UseAsyncValidatorExecuteReturn {
  pass: boolean
  errors: AsyncValidatorError['errors'] | undefined
  errorInfo: AsyncValidatorError | null
  errorFields: AsyncValidatorError['fields'] | undefined
}

export interface UseAsyncValidatorReturn {
  pass: ShallowRef<boolean>
  isFinished: ShallowRef<boolean>
  errors: ComputedRef<AsyncValidatorError['errors'] | undefined>
  errorInfo: ShallowRef<AsyncValidatorError | null>
  errorFields: ComputedRef<AsyncValidatorError['fields'] | undefined>
  execute: () => Promise<UseAsyncValidatorExecuteReturn>
}

各返回值的实际用途:

返回值 响应式类型 含义与典型场景
pass ShallowRef<boolean> 校验是否通过;模板中直接控制提交按钮 disabled
isFinished ShallowRef<boolean> 本轮校验是否结束;配合异步校验规则区分「校验中」与「完成」状态
errors ComputedRef<ValidateError[]> 错误数组,用于遍历渲染所有错误提示
errorFields ComputedRef<Record<string, ValidateError[]>> 按字段分组的错误对象,便于字段级提示
errorInfo ShallowRef<AsyncValidatorError | null> 最近一次校验的完整错误信息对象(含 errors 与 fields),无错误时为 null
execute() 函数 手动触发一次校验并返回 UseAsyncValidatorExecuteReturn(可 await)

由于返回值满足 PromiseLike,await useAsyncValidator(...) 会得到一次校验后的结果对象,适合在非模板场景(如提交回调中)快速做一次性校验。

声明式规则与响应式联动

规则 rules 完全沿用 async-validator 的 descriptor 格式,常用内建约束包括:

const rules = {
  username: [
    { required: true, message: '请输入用户名' },
    { min: 3, max: 20, message: '长度需在 3~20 之间' },
  ],
  email:   { type: 'email', required: true, message: '请输入合法邮箱' },
  age:     { type: 'number', min: 18, max: 99, message: '年龄超出范围' },
  url:     { type: 'url', message: 'URL 格式不合法' },
}

value 与 rules 的 MaybeRefOrGetter 支持意味着两种常见联动方式都是合法的:

// 1) 直接传 reactive 对象:数据变化即重校验
const form = reactive({ ... })
useAsyncValidator(form, rules)

// 2) 传 getter:按需读取最新值
useAsyncValidator(
  () => ({ password: form.password, confirm: form.confirm }),
  {
    confirm: {
      validator: (_rule, value) =>
        value === form.password ? Promise.resolve() : Promise.reject('两次密码不一致'),
    },
  },
)

后者尤其适合处理「两次密码一致」这类跨字段校验——自定义 validator 函数返回 Promise,正是 async-validator 异步能力的核心用法,useAsyncValidator 会将其结果纳入 pass / errorInfo 状态。

典型实战场景:注册表单提交校验

综合上述能力,一个完整的手动校验 + 自动状态联动的注册表单可以这样组织:

<script setup lang="ts">
import { reactive, ref } from 'vue'
import { useAsyncValidator } from '@vueuse/integrations/useAsyncValidator'

const form = reactive({ username: '', email: '', password: '' })
const rules = {
  username: { required: true, min: 3, message: '用户名至少 3 个字符' },
  email:    { type: 'email', required: true, message: '邮箱格式不正确' },
  password: { required: true, min: 8, message: '密码至少 8 位' },
}

// 自动校验 + 手动可重触发
const { pass, errorFields, execute } = useAsyncValidator(
  form, rules, { immediate: false, manual: true },
)

const submitting = ref(false)
async function handleSubmit() {
  const result = await execute()
  if (!result.pass) {
    // 按字段展示错误:errorFields.value.username
    return
  }
  submitting.value = true
  // ...调用业务接口
}
</script>

<template>
  <input v-model="form.username" />
  <p v-for="e in errorFields.username" :key="e.message">{{ e.message }}</p>
  <button :disabled="!pass || submitting" @click="handleSubmit">提交</button>
</template>

要点:errorFields 为字段分组错误,可直接按字段名取数组渲染;pass 作为 ShallowRef 在模板中自动解包,无需 .value。

仓库中的集成位置与使用约束

  • 技能归属:useAsyncValidator 收录在 airi 的 .agents/skills/vueuse-functions/references/useAsyncValidator.md,该技能库是面向 Vue 3 / Nuxt 3 开发决策的指南,由 vendor/vueuse/skills/vueuse-functions 同步而来(同步 SHA b6bb79b99fb1f1dba1f907829676a651735bbc10,见 SYNC.md)。
  • 依赖版本:仓库锁文件确认 @vueuse/integrations@14.4.0 存在且 async-validator 为其可选 peer 依赖(peerDependenciesMeta 中 optional),说明该函数在 airi 中属于「按需启用」能力,需要时通过 pnpm add async-validator@^4 激活(pnpm-lock.yaml)。
  • EXTERNAL 调用规则:按 SKILL.md 的约定,useAsyncValidator 归类为 @Integrations 且调用规则为 EXTERNAL,即仅当依赖已安装时才建议引入;若业务仅需同步校验,应先考虑内建逻辑而非额外引入该集成。

注意事项

  • async-validator@^4 与 @vueuse/integrations 的 peer 范围必须匹配:仓库锁文件显示 @vueuse/integrations@14.4.0 要求 async-validator: ^4,安装过低或过主版本可能导致类型不匹配。
  • validateOption 的可用字段随 async-validator 版本变化,以实际安装版本的类型声明为准。
  • immediate 默认 true:若不想在页面加载时立即弹错,请显式设置 immediate: false 或 manual: true。
  • 校验目标是 Record<string, any>:数组或嵌套结构需在规则中通过 type: 'array' / type: 'object' 及 fields 描述,或自行扁平化为对象后再传入。
登录后查看全文
airi