从表单校验看JavaScript策略模式的使用详解

作者:半夏

时间:2026-10-23

浏览:482

本文通过前端表单校验场景,深入解析JavaScript策略模式。针对传统if-else校验逻辑难以维护的问题,介绍如何封装策略对象与Context上下文,实现校验规则与调用逻辑分离。通过代码示例展示如何扩展多规则校验,提升代码可读性与复用性。

文章目录

前端表单校验的挑战

在前端开发中,表单占据了相当大的比重。几乎每一个中大型网站都需要通过“登录注册”等功能来验证用户信息,从而防止潜在的安全隐患。

因此,表单代码的质量成为前端开发者必须解决的关键问题。这直接关系到代码的可读性、可复用性以及是否过于冗杂。

有人可能会质疑表单是否真的有“优劣”之分。不妨仔细查看下方的代码,其中涉及了一些新的实现思路。


<form action="xxx" id="registerForm">
	请输入用户名:<input type="text" name="userName" id="name" />
	请输入密码:<input type="text" name="password" id="pass" />
	请输入手机号:<input type="text" name="phoneNumber" id="phone" />
	<button>提交</button>
</form>

用户名、密码和手机号是表单中最常见的字段,我们以此为例进行分析。

上述代码仅展示了简单的演示效果。实际上,开发者完全可以利用CSS的valid/invalid伪类,配合HTML5的required或pattern属性来完成基础校验。


<script>
	var registerForm=document.getElementById('registerForm')
	registerForm.onsubmit=function(){
		if(registerForm.userName.value==''){
			document.getElementById("name").setCustomValidity('用户名不能为空');
			return false;
		}
		if(registerForm.password.value.length<6){
			document.getElementById("pass").setCustomValidity('密码长度不能少于6位');
			return false;
		}
		if(!/(^1[3|5|8][0-9]{9}$)/.test(registerForm.phoneNumber.value)){
			document.getElementById("phone").setCustomValidity('手机号码格式不正确');
			return false;
		}
	}
</script>

然而,即便采用上述方式,代码依然不够完美。目前表单仅包含三条校验规则,若未来规则数量增加到N条,即使通过“复制粘贴”的方式也无法有效解决维护难题。

引入策略模式

此时,策略模式(Strategy Pattern)便成为理想的解决方案。在JavaScript中运用该模式时,应遵循“暴露接口与实现逻辑分离”的原则。

策略模式的核心在于定义一系列算法,并将它们分别封装起来。每个设计模式的共同主题是将不变部分与变化部分隔离,策略模式旨在将算法的使用者与算法的具体实现分离。一个基于策略模式的程序至少包含两部分:一是策略类,封装具体算法并负责计算;二是环境类Context,接收请求并将请求委托给特定的策略对象,这要求Context中维持对策略对象的引用。

策略对象封装与Context实现

第一步,我们需要将这些校验逻辑封装为【策略对象】。


var strategies={
	isNoneEmpty:function(value,errorMsg){
		if(value===''){
			return errorMsg;
		}
	},
	minLength:function(value,length,errorMsg){
		if(value.length<length){
			return errorMsg;
		}
	},
	isMobile:function(value,errorMsg){
		if(!/(^1[3|5|8][0-9]{9}$)/.test(value)){
			return errorMsg;
		}
	}
};

接下来,我们需要实现一个对外暴露的方法类,即作为Context(上下文)的调用接口。它负责接收用户请求,并将校验任务委托给具体的策略对象strategies。


var Validator=function(){
	this.cache=[]; //用于保存接收到的校验规则
};
Validator.prototype.add=function(dom,rule,errorMsg){
	var ary=rule.split(':');
	this.cache.push(function(){
		var strategy=ary.shift();
		ary.unshift(dom.value);
		ary.push(errorMsg);
		return strategies[strategy].apply(dom,ary); //调用strategies对象的指定方法对象,并规定在函数对象内部this指向dom元素,ary作为参数传入
	});
};
Validator.prototype.start=function(){
	for(var i=0,validatorFunc;validatorFunc=this.cache[i++];){
		var msg=validatorFunc();
		if(msg){
			return msg;
		}
	}
}

具体使用方式如下。


var validataFunc=function(){
	var validator=new Validator();
	
	//添加校验规则
	validator.add(registerForm.userName,'isNoneEmpty','用户名不能为空');
	validator.add(registerForm.password,'minLength:6','密码长度不能少于6位');
	validator.add(registerForm.phoneNumber,'isMobile','手机号码格式不正确');
	
	var errMsg=validator.start(); //获得校验结果
	return errorMsg; //返回
}

var registerForm=document.getElementById('registerForm')
registerForm.onsubmit=function(){
	var errorMsg=validataFunc();
	if(errorMsg){
		//触发错误提示
		return false; //并阻止表单提交
	}
}

观察代码可知,当向validator对象添加一系列校验规则后,需调用validator.start()方法来启动校验流程。如果validator.start()返回了明确的errorMsg字符串作为结果,说明校验未通过,此时应让registerForm.onsubmit方法返回false,以阻止表单提交。

这种实现方式相比之前有了显著改善,特别是在修改验证规则时显得轻松许多。


validator.add(registerForm.userName,'minLength:2','用户名不能少于2位')

多规则校验的扩展

但随之而来的问题是:若将用户名的验证规则从“不能为空”修改为“不能少于两位”,原有的“是否为空”校验将失效。

能否像element-ui那样支持自定义多种验证规则呢?例如采用以下形式。


validator.add(registerForm.userName,[{
	strategy:'isNoneEmpty',
	errorMsg:'用户名不能为空'
},{
	strategy:'minLength:2',
	errorMsg:'用户名长度不能少于2位'
}])

由于现在的“rule”参数变为数组-对象形式,我们需要对add函数进行相应调整。


Validator.prototype.add=function(dom,rules){
	var self=this;
	for(var i=0,rule;rule=rules[i++];){
		(function(rule){
			var strategyAry=rule.strategy.split(':');
			var errorMsg=rule.errorMsg;
			self.cache.push(function(){
				var strategy=strategyAry.shift();
				strategyAry.unshift(dom.value);
				return strategies[strategy].apply(dom,strategyAry);
			});
		})(rule)
	}
}

策略模式的优势

策略模式的主要优点如下。

该模式利用组合、委托和多态等技术思想,能有效避免多重条件选择语句(笔者在另一篇文章中对此有详细说明)。它完美实现了设计模式所倡导的“开闭原则”,基于策略模式实现的规则易于扩展和使用,从而避免了大量的复制粘贴工作。

至此,关于从表单校验看JavaScript策略模式的使用详解介绍完毕。如需了解更多相关JavaScript策略模式使用内容,请搜索本站以前的文章或继续浏览下面的相关文章,希望大家以后多多支持本站!

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章