人人都会AI编程

16.3 Element Plus / Ant Design Vue 表单校验

更新时间:2026-07-09

Element Plus 和 Ant Design Vue 的表单组件都内置了基于 async-validator 的校验能力,实际使用体验非常接近。你不需要额外安装校验库,直接在表单组件上声明校验规则即可。

核心三要素

无论用哪个库,表单校验都离不开三个部分:

  1. 表单数据对象:一个响应式对象,存储所有表单项的值。
  2. 校验规则对象:一个对象,键名对应表单字段,值是校验规则数组或单个规则。
  3. 表单实例引用:用于手动触发全局校验或清除校验结果。

Element Plus 表单校验

基础结构

<template>
  <el-form ref="formRef" :model="form" :rules="rules" label-width="80px">
    <el-form-item label="用户名" prop="username">
      <el-input v-model="form.username" />
    </el-form-item>
    <el-form-item label="邮箱" prop="email">
      <el-input v-model="form.email" />
    </el-form-item>
    <el-form-item>
      <el-button type="primary" @click="onSubmit">提交</el-button>
      <el-button @click="onReset">重置</el-button>
    </el-form-item>
  </el-form>
</template>

<script setup>
import { ref, reactive } from 'vue'

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

const rules = reactive({
  username: [
    { required: true, message: '请输入用户名', trigger: 'blur' },
    { min: 3, max: 10, message: '长度在 3 到 10 个字符', trigger: 'blur' }
  ],
  email: [
    { required: true, message: '请输入邮箱', trigger: 'blur' },
    { type: 'email', message: '邮箱格式不正确', trigger: ['blur', 'change'] }
  ]
})

const onSubmit = async () => {
  if (!formRef.value) return
  try {
    await formRef.value.validate()
    // 校验通过,提交数据
    console.log('提交:', form)
  } catch (err) {
    console.log('校验失败:', err)
  }
}

const onReset = () => {
  formRef.value?.resetFields()
}
</script>

关键点解析

  • el-formmodel 绑定数据对象,rules 绑定校验规则。
  • el-form-itemprop 必须与 model 中的字段名一致,否则校验不会生效。
  • 校验规则中 trigger 指定触发时机:'blur' 失焦时、'change' 值变化时,可以是数组。
  • formRef.value.validate() 返回 Promise,校验通过 resolve,失败 reject。
  • resetFields() 会清空表单值和校验状态。

常用规则类型
| 规则 | 用途 | 示例 |
|------|------|------|
| required | 必填 | { required: true, message: '不能为空' } |
| type | 数据类型 | 'email''url''number''date' |
| min / max | 字符串长度或数字大小 | { min: 6, max: 20, message: '6-20位' } |
| pattern | 正则校验 | { pattern: /^1[3-9]\d{9}$/, message: '手机号格式错误' } |
| validator | 自定义校验函数 | 见下文 |

自定义校验函数

const validatePassword = (rule, value, callback) => {
  if (value.length < 6) {
    callback(new Error('密码长度不能少于6位'))
  } else if (!/[A-Z]/.test(value)) {
    callback(new Error('密码需包含大写字母'))
  } else {
    callback() // 通过校验
  }
}

// 在 rules 中使用
password: [
  { required: true, message: '请输入密码', trigger: 'blur' },
  { validator: validatePassword, trigger: 'blur' }
]

注意:callback 必须调用,传入 Error 表示失败,不传或传空表示成功。

动态表单校验
当表单字段是动态循环生成的(如多个收货地址),prop 需要指向具体索引下的属性:

<el-form-item
  v-for="(item, index) in form.addresses"
  :key="index"
  :label="'地址' + (index + 1)"
  :prop="`addresses.${index}.street`"
  :rules="[{ required: true, message: '请输入地址' }]"
>
  <el-input v-model="item.street" />
</el-form-item>

手动触发单项校验

// 只校验邮箱字段
formRef.value.validateField('email', (valid) => {
  if (!valid) {
    console.log('邮箱不合法')
  }
})

滚动到第一个错误
默认 Element Plus 不会自动滚动。可以这样做:

const onSubmit = async () => {
  try {
    await formRef.value.validate()
  } catch {
    // 找到第一个错误项并滚动到它
    const firstError = document.querySelector('.is-error')
    firstError?.scrollIntoView({ behavior: 'smooth', block: 'center' })
  }
}

Ant Design Vue 表单校验

Ant Design Vue 3 的校验 API 几乎一致,只有组件名和少量细节差异。

基础结构

<template>
  <a-form ref="formRef" :model="form" :rules="rules" layout="vertical">
    <a-form-item label="用户名" name="username">
      <a-input v-model:value="form.username" />
    </a-form-item>
    <a-form-item label="邮箱" name="email">
      <a-input v-model:value="form.email" />
    </a-form-item>
    <a-form-item>
      <a-button type="primary" @click="onSubmit">提交</a-button>
      <a-button @click="onReset">重置</a-button>
    </a-form-item>
  </a-form>
</template>

<script setup>
import { ref, reactive } from 'vue'

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

const rules = {
  username: [
    { required: true, message: '请输入用户名', trigger: 'blur' },
    { min: 3, max: 10, message: '长度3-10', trigger: 'blur' }
  ],
  email: [
    { required: true, message: '请输入邮箱', trigger: 'blur' },
    { type: 'email', message: '邮箱格式不正确', trigger: 'blur' }
  ]
}

const onSubmit = () => {
  formRef.value.validate()
    .then(() => console.log('提交:', form))
    .catch(err => console.log('校验失败:', err))
}

const onReset = () => {
  formRef.value.resetFields()
}
</script>

与 Element Plus 的差异

  • a-form-item 使用 name 而非 prop 绑定字段。
  • v-model 双向绑定写法为 v-model:value="form.xxx"(或简写 v-model="form.xxx" 在新版中已支持)。
  • validate() 同样返回 Promise,用法无异。
  • 自定义校验函数的参数略有不同:(rule, value) => Promise,更推荐返回 Promise 而非使用 callback。
const validatePassword = (rule, value) => {
  if (value.length < 6) {
    return Promise.reject('密码长度不能少于6位')
  } else if (!/[A-Z]/.test(value)) {
    return Promise.reject('密码需包含大写字母')
  } else {
    return Promise.resolve()
  }
}

实战经验与避坑

1. 校验时机
生产环境中往往希望“提交时才校验,输入过程中只做实时提示”。可以将规则的 trigger 设为 'change',但提交时强制全部校验;也可以设 trigger: 'blur',兼顾体验。

2. 避免重复提交
校验是异步的,在 validate 过程中记得禁用按钮,防止多次点击。

<a-button type="primary" :loading="submitting" @click="onSubmit">提交</a-button>

3. 表单清空
resetFields() 会重置到初始值(即创建 form 时的默认值),而不是置空。如果你在数据加载后动态修改了 form 的值,再调用 resetFields() 会回退到最初状态,这可能导致预期不一致。建议在获取到数据后,重新赋值整个 form 对象,或手动逐个字段清空。

4. 嵌套对象校验
如果 model 是嵌套对象,如 { user: { name: '' } },则 prop 需写成 'user.name',且在 rules 中需要用 'user.name' 作为键名。Ant Design Vue 的 name 同样支持路径写法。

5. 动态规则
根据业务需要动态切换校验规则,可以将 rules 定义为计算属性:

const rules = computed(() => {
  const baseRules = { /* 基础规则 */ }
  if (isStrict.value) {
    baseRules.password.push({ pattern: /[!@#$%]/... })
  }
  return baseRules
})

6. 只校验部分字段
调用 validateField('email')validateFields(['email']),避免全量校验。


总结

Element Plus 和 Ant Design Vue 的表单校验都是配置式的,你只需定义好规则,调用 validate() 就能完成数据合法性检查。实际工作中绝大多数校验需求都能通过 requiredtypepattern 和简单的自定义函数解决。当遇到特别复杂的多字段联动校验(如“结束时间必须晚于开始时间”),可以在自定义 validator 中访问整个 model 对象来实现。