第一次接触Element UI的Form表单校验时,我被它的简洁设计惊艳到了。以前做表单验证要写一堆if-else判断,现在只需要几行配置就能搞定。先来看个最简单的例子:
javascript复制rules: {
username: [
{ required: true, message: '请输入用户名', trigger: 'blur' }
]
}
这段代码实现了最基本的非空校验。当输入框失去焦点时,如果内容为空就会显示错误提示。这里的trigger: 'blur'表示在失去焦点时触发验证,你也可以设置为'change'让它在内容变化时就验证。
实际项目中,我更喜欢把校验规则单独提取出来管理。比如新建一个validation.js文件:
javascript复制export const usernameRule = [
{ required: true, message: '请输入用户名', trigger: 'blur' },
{ min: 3, max: 16, message: '长度在3到16个字符', trigger: 'blur' }
]
然后在组件中引入使用:
javascript复制import { usernameRule } from './validation'
rules: {
username: usernameRule
}
这样做的好处是规则可以复用,而且组件代码更简洁。我在一个后台管理系统里,有20多个表单都用到了相同的用户名校验规则,修改时只需要改一处。
Element UI内置了丰富的数据类型校验,不用自己写正则表达式了。比如验证邮箱:
javascript复制email: [
{ type: 'email', message: '请输入正确的邮箱格式', trigger: 'blur' }
]
支持的type类型包括:
当内置类型不够用时,可以用pattern自定义正则:
javascript复制phone: [
{ pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号', trigger: 'blur' }
]
我在项目中遇到过需要验证特殊格式的情况,比如工号必须是"GD"开头加6位数字:
javascript复制employeeId: [
{ pattern: /^GD\d{6}$/, message: '工号格式为GD+6位数字', trigger: 'blur' }
]
min/max可以验证长度或数值范围:
javascript复制password: [
{ min: 6, max: 20, message: '密码长度在6到20位', trigger: 'blur' }
]
对于数字类型:
javascript复制age: [
{ type: 'number', min: 18, max: 60, message: '年龄必须在18到60岁', trigger: 'blur' }
]
实际项目中,密码强度校验是个常见需求。我们可以用validator自定义验证函数:
javascript复制const checkPassword = (rule, value, callback) => {
if (!value) {
return callback(new Error('请输入密码'))
}
if (!/[A-Z]/.test(value)) {
return callback(new Error('必须包含大写字母'))
}
if (!/[a-z]/.test(value)) {
return callback(new Error('必须包含小写字母'))
}
if (!/[0-9]/.test(value)) {
return callback(new Error('必须包含数字'))
}
callback()
}
rules: {
password: [
{ validator: checkPassword, trigger: 'blur' }
]
}
确认密码需要和原密码比较,这里要用到表单实例:
javascript复制const validatePass2 = (rule, value, callback) => {
if (value !== this.ruleForm.password) {
callback(new Error('两次输入密码不一致'))
} else {
callback()
}
}
rules: {
password2: [
{ validator: validatePass2, trigger: 'blur' }
]
}
比如检查用户名是否已存在:
javascript复制const checkUsername = (rule, value, callback) => {
if (!value) {
return callback(new Error('请输入用户名'))
}
api.checkUsername(value).then(exists => {
if (exists) {
callback(new Error('用户名已存在'))
} else {
callback()
}
})
}
rules: {
username: [
{ validator: checkUsername, trigger: 'blur' }
]
}
我做过一个订单表单,需要根据支付方式校验不同字段:
javascript复制const validatePayment = (rule, value, callback) => {
if (this.form.paymentType === 'creditCard' && !value) {
callback(new Error('信用卡支付需要填写卡号'))
} else if (this.form.paymentType === 'alipay' && !value) {
callback(new Error('请填写支付宝账号'))
} else {
callback()
}
}
当字段之间有依赖关系时:
javascript复制const validateAddress = (rule, value, callback) => {
if (this.form.needDelivery && !value) {
callback(new Error('请填写配送地址'))
} else {
callback()
}
}
有时候需要根据条件切换校验规则:
javascript复制watch: {
'form.type'(newVal) {
if (newVal === 'vip') {
this.rules.phone = [
{ required: true, message: 'VIP用户必须填写手机号', trigger: 'blur' }
]
} else {
this.rules.phone = []
}
}
}
对于复杂的表单,可以通过validate-on-rule-change属性控制:
html复制<el-form :validate-on-rule-change="false">
可以自定义错误显示方式:
javascript复制rules: {
username: [
{
required: true,
message: h => h('div', [
h('span', { style: 'color: red' }, '错误:'),
h('span', '请输入用户名')
]),
trigger: 'blur'
}
]
}
在提交时统一校验:
javascript复制submitForm() {
this.$refs.form.validate(valid => {
if (valid) {
// 提交逻辑
} else {
this.$message.error('请检查表单')
return false
}
})
}
prop属性是否和v-model绑定的字段名一致rules已正确绑定到el-form对于动态增减的表单项,需要特殊处理:
javascript复制rules: {
dynamicItems: {
type: 'array',
required: true,
min: 1,
message: '至少添加一项',
fields: {
0: { /* 第一项的规则 */ },
1: { /* 第二项的规则 */ }
}
}
}
有时候需要访问其他字段值:
javascript复制const validateEndDate = (rule, value, callback) => {
if (value < this.form.startDate) {
callback(new Error('结束日期不能早于开始日期'))
} else {
callback()
}
}
完整示例:
javascript复制rules: {
username: [
{ required: true, message: '请输入用户名', trigger: 'blur' },
{ min: 4, max: 16, message: '长度在4到16个字符', trigger: 'blur' },
{ pattern: /^[a-zA-Z0-9_]+$/, message: '只能包含字母、数字和下划线', trigger: 'blur' }
],
password: [
{ required: true, message: '请输入密码', trigger: 'blur' },
{ min: 8, message: '至少8个字符', trigger: 'blur' },
{ validator: checkPasswordStrength, trigger: 'blur' }
],
phone: [
{ required: true, message: '请输入手机号', trigger: 'blur' },
{ pattern: /^1[3-9]\d{9}$/, message: '手机号格式不正确', trigger: 'blur' }
],
captcha: [
{ required: true, message: '请输入验证码', trigger: 'blur' },
{ len: 6, message: '验证码为6位数字', trigger: 'blur' }
]
}
包含复杂业务规则:
javascript复制rules: {
price: [
{
validator: (rule, value, callback) => {
if (this.form.isDiscount && value < this.form.originalPrice * 0.5) {
callback(new Error('折扣价不能低于原价50%'))
} else {
callback()
}
},
trigger: 'blur'
}
]
}
带条件校验:
javascript复制rules: {
endDate: [
{
validator: (rule, value, callback) => {
if (this.form.dateRange && !value) {
callback(new Error('请选择结束日期'))
} else {
callback()
}
},
trigger: 'change'
}
]
}