如何优雅的进行表单校验

299 阅读1分钟

工作中,我们经常会遇到表单信息提交时,需要校验表单格式,拦截无效请求,此时不可避免的就是用大量的if return去拦截。还要重复写大量的errorMessage,如下场景:

// 下面是业务场景的字段及格式要求
	userName:必填,
	phone: 必填,正则验证,已设置max = 11
	address:至少两位,已设置max = 150

一般的代码逻辑校验会这么写:

// formData
const {
	userName,
	phone,
	address = ''
} = formData;
if (!userName) {
	showErrorMsg('userName is required');
	return;					
}
if (!phone) {
	showErrorMsg('phone is required');
	return;					
}
const reg = /^1[3456789]\d{9}$/;
if (!reg.test(phone)) {
	showErrorMsg('Please check the phone in the correct format');
	return;
}
if (address.length < 2) {
	showErrorMsg('address needs two words at least');
	return;
}
// 如果还有其他相同的字段格式,还是要写if...
// post formdata...

有大量的if returnshowErrorMsg显得不是很优雅,并且如果遇到不同字段的相同的格式要求(譬如userName和phone都是必填项,但写了两次if)那能不能只写一次呢?根据场景,只要一个字段校验不通过就可以return了,那就可以通过forEach + try catch的方式进行捕获错误信息,如下:

// formData
const {
	userName,
	phone,
	address = ''
} = formData;

let isCheck = true;
// 填写错误规则 
const rules = {
	userName: {
		required: 'userName is required',
	},
	phone: {
		required: 'phone is required',
		regex: {
			reg: /^1[3456789]\d{9}$/,
			msg: 'Please check the phone in the correct format'
		}
	},
	address: {
		min: {
			limit: 2,
			msg: 'address needs two words at least'
		}
	}
};
// forEach 校验
try {
	Object.keys(formData).forEach(item => {
		const ruleItem = rules[item];
		if (!ruleItem) {
			return;
		}
		const formItem = formData[item];
		if (ruleItem.required && !formItem) {
			throw ruleItem.required;
		}
		if (ruleItem.regex && !regex.reg.test(formItem)) {
			throw ruleItem.regex.msg;
		}
		if (ruleItem.min && formItem < ruleItem.min.limit) {
			throw ruleItem.min.msg;
		}
		// ..其他规则,所有的规则只需要写一次
	})
} catch (err) {
	isCheck = false;
	showErrorMsg(err);
	// 校验结果,视情景需要
	// return isCheck;
	return;
}
// post formData...

代码经过了上面的处理,所有的规则只需要写一次即可判断,这样就可以单独将校验函数抽出来进行封装,只需开发者传入校验规则和校验的数据就可以得到校验结果返回true or false了。这样是不是更加方便优雅了呢。 同样的也有一个弊端,这样的写法也对格式要求比较严格,期待大家留言给我更好的想法。