第 8 章:实战应用场景
2025/9/1大约 4 分钟
// 综合表单验证器
class FormValidator {
constructor() {
this.validators = {
email: this.validateEmail,
phone: this.validatePhone,
password: this.validatePassword,
url: this.validateUrl,
date: this.validateDate,
creditCard: this.validateCreditCard,
idCard: this.validateIdCard
};
}
validateEmail(value) {
const pattern = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
return {
valid: pattern.test(value) && value.length <= 254,
message: pattern.test(value) ? '' : '请输入有效的邮箱地址'
};
}
validatePhone(value, country = 'china') {
const patterns = {
china: /^1[3-9]\d{9}$/,
usa: /^[2-9]\d{2}[2-9]\d{2}\d{4}$/,
international: /^\+?[1-9]\d{1,14}$/
};
const cleanValue = value.replace(/\D/g, '');
const pattern = patterns[country] || patterns.international;
const valid = pattern.test(cleanValue);
return {
valid,
message: valid ? '' : `请输入有效的${country === 'china' ? '中国' : ''}手机号码`
};
}
validatePassword(value, options = {}) {
const {
minLength = 8,
requireUppercase = true,
requireLowercase = true,
requireNumbers = true,
requireSpecialChars = true
} = options;
const errors = [];
if (value.length < minLength) {
errors.push(`密码长度至少${minLength}位`);
}
if (requireUppercase && !/[A-Z]/.test(value)) {
errors.push('必须包含大写字母');
}
if (requireLowercase && !/[a-z]/.test(value)) {
errors.push('必须包含小写字母');
}
if (requireNumbers && !/\d/.test(value)) {
errors.push('必须包含数字');
}
if (requireSpecialChars && !/[!@#$%^&*(),.?":{}|<>]/.test(value)) {
errors.push('必须包含特殊字符');
}
return {
valid: errors.length === 0,
message: errors.join(',')
};
}
validateUrl(value) {
const pattern = /^https?:\/\/(?:[-\w.])+(?:\:[0-9]+)?(?:\/(?:[\w\/_.])*)?(?:\?(?:[\w&=%.])*)?(?:\#(?:[\w.])*)?$/;
return {
valid: pattern.test(value),
message: pattern.test(value) ? '' : '请输入有效的URL地址'
};
}
validateDate(value, format = 'YYYY-MM-DD') {
const patterns = {
'YYYY-MM-DD': /^\d{4}-\d{2}-\d{2}$/,
'DD/MM/YYYY': /^\d{2}\/\d{2}\/\d{4}$/,
'MM/DD/YYYY': /^\d{2}\/\d{2}\/\d{4}$/
};
const pattern = patterns[format];
if (!pattern || !pattern.test(value)) {
return {
valid: false,
message: `请输入有效的日期格式(${format})`
};
}
// 验证日期有效性
let date;
if (format === 'YYYY-MM-DD') {
date = new Date(value);
} else {
const parts = value.split(/[\/\-]/);
if (format === 'DD/MM/YYYY') {
date = new Date(parts[2], parts[1] - 1, parts[0]);
} else { // MM/DD/YYYY
date = new Date(parts[2], parts[0] - 1, parts[1]);
}
}
const valid = !isNaN(date.getTime());
return {
valid,
message: valid ? '' : '请输入有效的日期'
};
}
validateCreditCard(value) {
const cleanValue = value.replace(/\D/g, '');
// Luhn算法验证
const luhnCheck = (num) => {
let sum = 0;
let isEven = false;
for (let i = num.length - 1; i >= 0; i--) {
let digit = parseInt(num[i]);
if (isEven) {
digit *= 2;
if (digit > 9) digit -= 9;
}
sum += digit;
isEven = !isEven;
}
return sum % 10 === 0;
};
const cardTypes = {
visa: /^4\d{12}(\d{3})?$/,
mastercard: /^5[1-5]\d{14}$/,
amex: /^3[47]\d{13}$/,
discover: /^6011\d{12}$/
};
let cardType = 'unknown';
for (const [type, pattern] of Object.entries(cardTypes)) {
if (pattern.test(cleanValue)) {
cardType = type;
break;
}
}
const valid = cardType !== 'unknown' && luhnCheck(cleanValue);
return {
valid,
cardType,
message: valid ? '' : '请输入有效的信用卡号码'
};
}
validateIdCard(value) {
// 中国身份证号验证
const pattern = /^\d{17}[\dXx]$/;
if (!pattern.test(value)) {
return {
valid: false,
message: '身份证号码格式不正确'
};
}
// 校验码验证
const weights = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
const codes = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];
let sum = 0;
for (let i = 0; i < 17; i++) {
sum += parseInt(value[i]) * weights[i];
}
const expectedCode = codes[sum % 11];
const actualCode = value[17].toUpperCase();
return {
valid: expectedCode === actualCode,
message: expectedCode === actualCode ? '' : '身份证号码校验失败'
};
}
// 批量验证
validateForm(formData, rules) {
const results = {};
let isValid = true;
for (const [field, value] of Object.entries(formData)) {
if (rules[field]) {
const rule = rules[field];
const validator = this.validators[rule.type];
if (validator) {
const result = validator.call(this, value, rule.options);
results[field] = result;
if (!result.valid) {
isValid = false;
}
}
}
}
return {
valid: isValid,
fields: results
};
}
}
// 使用示例
const validator = new FormValidator();
const formData = {
email: 'user@example.com',
phone: '13812345678',
password: 'MyPassword123!',
website: 'https://example.com',
birthday: '1990-01-01',
creditCard: '4111111111111111'
};
const validationRules = {
email: { type: 'email' },
phone: { type: 'phone', options: 'china' },
password: {
type: 'password',
options: {
minLength: 8,
requireSpecialChars: true
}
},
website: { type: 'url' },
birthday: { type: 'date', options: 'YYYY-MM-DD' },
creditCard: { type: 'creditCard' }
};
const result = validator.validateForm(formData, validationRules);
console.log('表单验证结果:', result);
// 输出各字段验证信息
Object.entries(result.fields).forEach(([field, validation]) => {
console.log(`${field}: ${validation.valid ? '有效' : validation.message}`);
});
小结
本章通过实战案例展示了正则表达式在各种场景中的应用:
- 邮箱验证:从简单到复杂,考虑国际化支持
- 电话号码:支持多国格式,提供格式化功能
- URL处理:验证、解析、提取各类链接
- 密码强度:多层次验证,安全策略实现
- 日期时间:多格式支持,智能解析
- IP地址:IPv4/IPv6验证,地址分类
- 综合应用:完整的表单验证器实现
通过这些实战案例,我们可以看到正则表达式在实际开发中的强大威力和广泛应用。掌握这些常见模式可以大大提高开发效率和数据验证的准确性。
练习题
练习1:社交媒体提取器
编写一个函数,从文本中提取所有的社交媒体链接(Twitter、Facebook、Instagram等)。
练习2:车牌号验证器
编写一个中国车牌号验证器,支持新能源车牌和传统车牌格式。
练习3:文档解析器
编写一个简单的Markdown解析器,提取标题、链接、图片等元素。
这些练习将帮助你进一步巩固正则表达式在实际项目中的应用技能。