每日一题:自定义表单验证器

介绍

自定义表单验证器是一种在 Web 开发中常用的技术,用于验证用户输入的数据是否符合特定的规则或要求。通过自定义表单验证器,我们可以对表单字段进行验证,并在用户提交表单之前检查数据的有效性。

准备

本题已经内置了初始代码,打开实验环境,目录结构如下:

1
2
3
4
5
6
7
8
9
├── components
│ ├── FormInput.js
│ └── FormValidator.js
├── css
├── index.html
├── js
│ └── util.js
└── lib
└── vue.global.js

其中:

  • index.html 是主页面。
  • css 是存放项目样式的文件夹。
  • lib 是存放项目依赖的文件夹。
  • components/FormInput.jsinput 组件。
  • components/FormValidator.js 是表单验证器组件。
  • js/util.js 是项目需要用到的工具函数。

注意:打开环境后发现缺少项目代码,请手动键入下述命令进行下载:

1
2
cd /home/project
file="formval" && wget "https://labfile.oss.aliyuncs.com/courses/19791/${file}.zip" && unzip "${file}.zip" && rm "${file}.zip"

选中 index.html 右键启动 Web Server 服务(Open with Live Server),让项目运行起来。接着,打开环境右侧的【Web 服务】,就可以在浏览器中看到如下效果:

初始效果

目标

  1. 完成 FormInput.js 中的 TODO 部分,当输入框(class= form-input) 的值变化时,触发事件更新index.html 中组件(form-input)的 v-model 值。(调试 tips:考生可以在点击按钮时通过打印 formData 的值进行查看)。
  2. 完成 js/util.js 中的 is_email 函数,参数是邮箱地址,是合法邮箱返回 true,否则返回 false

合法邮箱包含两个部分:

  1. 用户名部分:
    • 用户名的结尾是 @ 符。
    • @ 符之前为至少 1 位字符(数字或字母)。
  2. 域名部分:
    • 中间必须是 .
    • . 之前为至少 1 位字符(数字、字母)。
    • . 之后为 2 到 4 位字母。

合法邮箱示例: a@b.cn1A@88.com

不合邮箱示例: 1@1.c1@33.cnAb.cn@

  1. 完成 components/FormValidator.js 中通用表单验证函数 validateForm 中的 TODO 部分。如果表单验证通过,则 Promiseresolve(true),否则为 resolve(false)(此部分代码已提供)。 index.html 中定义的 formRules 对象对应字段的表单值验证失败时,使用 validateForm 函数中提供的 errors 对象,在对应字段中存储错误信息。若某个字段对应的错误信息为多个时,将按照验证规则数组的顺序优先显示,即只显示第一个错误信息。函数使用的数据通过 props.rules(字段名和对应的验证规则) 和 props.formData(表单数据的键值对) 进行获取。

例: email为空显示了错误信息 邮箱不能为空,则不再显示 邮箱不符合规则或者长度不符 这个错误信息。

errors 数据结构示例:

1
2
3
4
{
phone: "请输入密码", // 对应字段为 phone 的错误信息
email: "邮箱不能为空" // 对应字段为 email 的错误信息
}

表单每个字段对应的验证规则为一个数组,验证规则示例的配置如下:

1
2
3
4
5
6
7
8
// 定义表单验证规则
const formRules = {
phone: [{ validator: validatePass }], // 针对 phone 字段的验证规则
email: [
{ required: true, message: "邮箱不能为空" }, // 邮箱字段必填规则
{ type: "email", min: 8, max: 20, message: "类型必须为邮箱" }, // 邮箱格式规则
],
};

formRules 对应字段说明如下:

注意:自定义验证函数 validator 不会和其他字段同时出现,其他字段均可同时出现。

参数名(Parameter) 类型(Type) 描述(Description)
validator Function 表单自定义验证函数,接受三个参数,分别为 rule 表单验证规则数组,value 验证表单的值,callback 回调函数。如果验证成功,callback 函数不做任何处理;如果验证失败,callback 函数接收参数 error 并将其中的文字存储在 errors 对象中,且参数 error 的值为其调用者传递过来的 new Error('这里是错误信息'),其中错误信息是验证失败的具体描述。callback 函数的调用逻辑 index.html 中已经提供,考生只需实现字段验证及 errors 错误信息存储的逻辑即可。
required Boolean 表示表单字段是否为必填项。
type String 字段类型,通过 FormValidator 中已提供的 validateByType 函数进行验证,该函数接收的参数为 type,类型正确则返回 true,否则返回 false
min Number 指定表单输入的最小长度。
max Number 指定表单输入的最大长度。
message String 验证失败时的错误信息

完成后示例效果如下:

完成效果

规定

  • 请严格按照考试步骤操作,切勿修改考试默认提供项目中的文件名称、文件夹路径、class 名、id 名、图片名等,以免造成判题无法通过。

判分标准

  • 完成目标 1,得 5 分。
  • 完成目标 2,得 5 分。
  • 完成目标 3,得 15 分。

总通过次数: 61 | 总提交次数: 162 | 通过率: 37.7%

题解

1
2
3
4
5
6
//  TODO:目标 1 当输入框的值变化时,触发 input 事件更新父组件的 v-model 值
watch(inputValue, (value) => {
emit('update:modelValue', value)
})

// TODO:end
1
2
3
4
const is_email = (val) => {
// TODO:目标 2 待补充代码
return /^[A-Za-z0-9\u4e00-\u9fa5]+@[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(?:\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+$/.test(val)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// TODO:目标 3 编写通用的表单验证规则,并将错误信息放置到 errors 对象中
console.log(props.rules);
console.log(Object.keys(props.formData));
for(let key of Object.keys(props.formData)) {
// console.log(props.formData[key]);
for(let rule of props.rules[key]) {
console.log(rule);
if (key in errors) {
break
}
// console.log('validator' in rule);
if ('validator' in rule) {
rule.validator(rule, props.formData[key], (error) => {if(error) errors.value[key] = error.message})
}
if ('required' in rule) {
if (rule.required && props.formData[key] === '') {
errors.value[key] = rule.message
}
}
if ('type' in rule && rule.type === 'email') {
if (!validateByType(rule.type, props.formData[key]) || props.formData[key].length < rule.min || props.formData[key].length > rule.max) {
errors.value[key] = rule.message
}
}
}
}
// TODO:END