各位观众老爷,晚上好!欢迎来到今天的“Vue 表单校验炼金术”讲座。咱们今天不搞虚的,直接上干货,一起研究如何用 Vue 的响应式系统和 Composition API,打造一个既强大又灵活的表单校验库。
第一章:表单校验的需求分析与设计思想
在开始敲代码之前,咱们先捋捋思路。一个好的表单校验库,至少要满足以下几个需求:
- 声明式校验规则: 能用简洁的方式定义校验规则,比如必填、长度限制、邮箱格式等等。
- 实时响应: 用户输入时,能够实时校验并显示错误信息。
- 可扩展性: 方便添加自定义校验规则,以应对各种奇葩的需求。
- 易于维护: 代码结构清晰,方便修改和调试。
- 良好的用户体验: 错误信息提示友好,引导用户正确填写。
为了满足这些需求,我们的设计思想是:
- 响应式驱动: 利用 Vue 的响应式系统,监听表单数据的变化,自动触发校验。
- Composition API 封装: 将校验逻辑封装成独立的 Composition 函数,提高代码复用性和可维护性。
- 规则引擎: 设计一个规则引擎,负责解析和执行校验规则。
- 错误信息管理: 统一管理错误信息,方便显示和处理。
第二章:搭建项目骨架与核心概念
咱们先创建一个 Vue 项目(用 Vue CLI),然后创建一个 src/composables/useFormValidation.js
文件,这里将是我们的核心代码所在地。
接下来,定义几个核心概念:
- Field: 表示一个需要校验的表单字段,包含字段名、值和校验规则。
- Rule: 表示一个校验规则,包含规则名称、参数和校验函数。
- Validator: 负责执行校验规则,并返回校验结果。
- Error: 表示一个校验错误,包含字段名和错误信息。
第三章:useFormValidation
的基本结构
咱们先搭起 useFormValidation
的基本结构,先让它能跑起来再说:
// src/composables/useFormValidation.js
import { reactive, computed } from 'vue';
export function useFormValidation(formConfig) {
// 1. 定义响应式状态
const fields = reactive({}); // 用于存储所有字段的值
const errors = reactive({}); // 用于存储所有错误信息
// 2. 初始化字段
for (const fieldName in formConfig) {
fields[fieldName] = ''; // 初始化字段值为空字符串,可以根据实际情况调整
errors[fieldName] = null; // 初始化错误信息为空
}
// 3. 校验函数 (先占个坑,后面再完善)
const validateField = (fieldName) => {
console.log(`校验字段: ${fieldName}`);
return true; // 暂时返回 true,表示校验通过
};
// 4. 提交函数 (先占个坑,后面再完善)
const handleSubmit = () => {
console.log('提交表单');
};
// 5. 返回响应式数据和方法
return {
fields,
errors,
validateField,
handleSubmit,
};
}
这个简单的 useFormValidation
已经可以用了。 formConfig
是一个对象,定义了表单中需要校验的字段。 fields
存储字段的值, errors
存储错误信息。 validateField
和 handleSubmit
是两个占位函数,后面会逐步完善。
第四章:定义校验规则
接下来,咱们定义一些常用的校验规则。 创建一个 src/utils/rules.js
文件:
// src/utils/rules.js
export const required = (value) => {
if (!value) {
return '必填';
}
return null;
};
export const minLength = (value, length) => {
if (value && value.length < length) {
return `至少输入 ${length} 个字符`;
}
return null;
};
export const maxLength = (value, length) => {
if (value && value.length > length) {
return `最多输入 ${length} 个字符`;
}
return null;
};
export const email = (value) => {
if (value && !/^[^s@]+@[^s@]+.[^s@]+$/.test(value)) {
return '邮箱格式不正确';
}
return null;
};
// 可以根据需要添加更多规则,比如手机号、身份证号等等
这些规则都是简单的函数,接收字段值作为参数,如果校验失败,返回错误信息;如果校验成功,返回 null
。
第五章:完善 useFormValidation
,实现规则引擎
现在,咱们回到 useFormValidation.js
,完善校验逻辑:
// src/composables/useFormValidation.js
import { reactive, computed, watch } from 'vue';
import * as rules from '../utils/rules';
export function useFormValidation(formConfig) {
const fields = reactive({});
const errors = reactive({});
const isFormValid = reactive({value: true}); // 新增: 表单整体是否有效
// 初始化字段
for (const fieldName in formConfig) {
fields[fieldName] = '';
errors[fieldName] = null;
}
// 校验函数
const validateField = (fieldName) => {
const rulesForField = formConfig[fieldName];
let error = null;
for (const ruleName in rulesForField) {
const ruleValue = rulesForField[ruleName];
// 如果 rules 中存在对应的规则,则执行校验
if (rules[ruleName]) {
error = rules[ruleName](fields[fieldName], ruleValue);
if (error) {
break; // 只要有一个规则校验失败,就停止校验
}
} else {
console.warn(`未找到规则: ${ruleName}`);
}
}
errors[fieldName] = error; // 更新错误信息
return !error; // 返回校验结果
};
// 监听字段变化,自动校验
for (const fieldName in formConfig) {
watch(() => fields[fieldName], () => {
validateField(fieldName);
});
}
// 新增: 校验所有字段
const validateAll = () => {
let isValid = true;
for (const fieldName in formConfig) {
if (!validateField(fieldName)) {
isValid = false;
}
}
isFormValid.value = isValid;
return isValid;
}
// 提交函数
const handleSubmit = () => {
if (validateAll()) { // 先校验所有字段
console.log('表单校验通过,可以提交数据了', fields);
} else {
console.log('表单校验失败,请检查错误信息');
}
};
// 返回响应式数据和方法
return {
fields,
errors,
validateField,
handleSubmit,
validateAll,
isFormValid
};
}
这个版本的 useFormValidation
已经具备了基本的校验功能:
- 规则引擎:
validateField
函数遍历字段的校验规则,并执行对应的校验函数。 - 实时校验:
watch
函数监听字段值的变化,自动触发校验。 - 错误信息更新: 校验结果会更新到
errors
对象中。 validateAll
: 用于校验所有字段isFormValid
: 响应式表单是否有效标志
第六章:在组件中使用 useFormValidation
现在,咱们在一个 Vue 组件中使用 useFormValidation
:
// App.vue
<template>
<form @submit.prevent="handleSubmit">
<div>
<label for="email">邮箱:</label>
<input type="email" id="email" v-model="fields.email">
<p v-if="errors.email" class="error">{{ errors.email }}</p>
</div>
<div>
<label for="password">密码:</label>
<input type="password" id="password" v-model="fields.password">
<p v-if="errors.password" class="error">{{ errors.password }}</p>
</div>
<div>
<button type="submit" :disabled="!isFormValid.value">提交</button>
</div>
<p v-if="!isFormValid.value">表单有错误,请检查</p>
</form>
</template>
<script>
import { useFormValidation } from './composables/useFormValidation';
export default {
setup() {
const formConfig = {
email: {
required: true,
email: true,
},
password: {
required: true,
minLength: 6,
maxLength: 20,
},
};
const { fields, errors, handleSubmit, isFormValid } = useFormValidation(formConfig);
return {
fields,
errors,
handleSubmit,
isFormValid
};
},
};
</script>
<style scoped>
.error {
color: red;
}
</style>
在这个组件中,咱们定义了 email
和 password
两个字段的校验规则。 v-model
双向绑定字段值, v-if
根据错误信息显示错误提示。 handleSubmit
处理表单提交,会先校验所有字段。
第七章:添加自定义校验规则
如果内置的校验规则不够用,咱们可以添加自定义校验规则。 比如,咱们要添加一个校验用户名是否存在的规则:
- 定义自定义规则:
// src/utils/rules.js
export const usernameExists = async (value) => {
// 模拟异步校验
await new Promise(resolve => setTimeout(resolve, 500));
if (value === 'admin') {
return '用户名已存在';
}
return null;
};
- 在
formConfig
中使用:
// App.vue
const formConfig = {
username: {
required: true,
usernameExists: true, // 使用自定义规则
},
// ...
};
- 修改
useFormValidation
: (重要!) 异步校验需要特殊处理,防止并发问题。
// src/composables/useFormValidation.js
// 在 validateField 中
for (const ruleName in rulesForField) {
const ruleValue = rulesForField[ruleName];
// 如果 rules 中存在对应的规则,则执行校验
if (rules[ruleName]) {
const ruleFn = rules[ruleName];
// 处理异步校验
if (ruleFn.constructor.name === 'AsyncFunction') {
error = await ruleFn(fields[fieldName], ruleValue);
} else {
error = ruleFn(fields[fieldName], ruleValue);
}
if (error) {
break; // 只要有一个规则校验失败,就停止校验
}
} else {
console.warn(`未找到规则: ${ruleName}`);
}
}
第八章:更高级的用法与优化
- 错误信息国际化: 可以将错误信息存储在单独的文件中,根据用户的语言环境显示不同的错误提示。
- 自定义错误信息: 允许用户自定义每个规则的错误信息,提供更灵活的错误提示。
- 节流/防抖: 对于一些复杂的校验规则,可以使用节流或防抖来优化性能。 (例如,输入框搜索提示)
- 表单重置: 提供一个重置表单的方法,将所有字段的值和错误信息重置为初始状态。
- 分组校验: 将表单字段分组,可以单独校验某个分组的字段。
第九章:总结与展望
咱们今天一起用 Vue 的响应式系统和 Composition API,实现了一个可扩展、可维护的表单校验库。 这个库虽然简单,但已经具备了核心功能。 通过不断完善和优化,它可以满足各种复杂的表单校验需求。
特性 | 优点 | 缺点 |
---|---|---|
Composition API | 代码组织清晰,复用性高,易于测试。 | 上手难度略高,需要理解响应式系统的原理。 |
响应式系统 | 实时响应,自动更新,无需手动触发校验。 | 可能导致性能问题,需要注意优化。 |
规则引擎 | 灵活可扩展,方便添加自定义规则。 | 需要考虑规则的优先级和执行顺序。 |
错误信息管理 | 统一管理错误信息,方便显示和处理。 | 需要考虑错误信息的国际化和自定义。 |
希望今天的讲座对大家有所帮助。 表单校验是一个看似简单,实则充满挑战的任务。 只有不断学习和实践,才能掌握其中的奥秘。 感谢各位的观看,咱们下次再见!