Detailed explanation of the use of JavaScript policy mode from form verification

  • 2021-08-31 07:10:36
  • OfStack

As we all know, forms do occupy a large proportion in the front end, well, or in the web page. In fact, almost every large and medium-sized website will have "login registration" to verify user information and prevent some indescribable hidden dangers. . .

Then the advantages and disadvantages of the form have become an urgent problem for front-end developers. In fact, I prefer to call it "readability of code" or "reusability" and "whether it is jumbled or not".

Forms also have "advantages and disadvantages"? Are you kidding?
I think you can take a closer look at the following code, which uses some "new knowledge":


<form action="xxx" id="registerForm">
	 Please enter a user name: <input type="text" name="userName" id="name" />
	 Please enter your password: <input type="text" name="password" id="pass" />
	 Please enter your mobile phone number: <input type="text" name="phoneNumber" id="phone" />
	<button> Submit </button>
</form>

User name, password and mobile phone number should be the most common ones in the form. OK, let's analyze them!

These are just simple demonstration effects, and you can use valid/invalid of css and required/pattern of HTML5 to complete them.


<script>
	var registerForm=document.getElementById('registerForm')
	registerForm.onsubmit=function(){
		if(registerForm.userName.value==''){
			document.getElementById("name").setCustomValidity(' User name cannot be empty ');
			return false;
		}
		if(registerForm.password.value.length<6){
			document.getElementById("pass").setCustomValidity(' Password length cannot be less than 6 Bit ');
			return false;
		}
		if(!/(^1[3|5|8][0-9]{9}$)/.test(registerForm.phoneNumber.value)){
			document.getElementById("phone").setCustomValidity(' The mobile phone number format is incorrect ');
			return false;
		}
	}
</script>

But even so, you won't find it perfect-there are only three forms now, and if it increases to N one day, even "copy and paste" won't save you!

That's when you think of the strategy mode (see, JS always gives you an "epiphany")
Speaking of policy patterns, it is natural to follow the principle of exposing interfaces and implementing logical separation.

Policy pattern refers to defining a series of algorithms and encapsulating them one by one. Separating the invariant from the changing is the theme of every design pattern, and the policy pattern is no exception. The purpose of the policy pattern is to separate the use of the algorithm from the implementation of the algorithm.
A program based on policy pattern consists of at least two parts. The first part is a group of policy classes, which encapsulate the specific algorithm and take charge of the specific calculation process. The second part is the environment class Context, where Context accepts a request from a customer and then delegates the request to a policy class. To do this, explain that you want to maintain a reference to a policy object in Context
-"JavaScript Design Pattern and Development Practice"

Then, in the first step, we obviously want to encapsulate all these validation logics as "policy objects":


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;
		}
	}
};

Next, we implement an "exposed", "as called" method class--which will act as an context (context) and be responsible for receiving the user's request and delegating it to the validation object stratrgies:


var Validator=function(){
	this.cache=[]; // Used to save the received verification rules 
};
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); // Call strategies The specified method object of the object, and it is specified within the function object this Point dom Element, ary Pass in as a parameter 
	});
};
Validator.prototype.start=function(){
	for(var i=0,validatorFunc;validatorFunc=this.cache[i++];){
		var msg=validatorFunc();
		if(msg){
			return msg;
		}
	}
}

Use:


var validataFunc=function(){
	var validator=new Validator();
	
	// Add Verification Rules 
	validator.add(registerForm.userName,'isNoneEmpty',' User name cannot be empty ');
	validator.add(registerForm.password,'minLength:6',' Password length cannot be less than 6 Bit ');
	validator.add(registerForm.phoneNumber,'isMobile',' The mobile phone number format is incorrect ');
	
	var errMsg=validator.start(); // Obtain verification results 
	return errorMsg; // Return 
}

var registerForm=document.getElementById('registerForm')
registerForm.onsubmit=function(){
	var errorMsg=validataFunc();
	if(errorMsg){
		// Trigger error prompt 
		return false; // And block form submission 
	}
}

What we can see is that after we have added 1 series of validation rules to the validator object, we will call validator.start() Method to start validation. If validator.start() Returned an exact errorMsg string as the return value, indicating that the check failed, at this time, it is necessary to let registerForm.onsubmit Method returns false to prevent submission of the form.

This is really much better than before: at least it seems effortless when we modify the validation rules:


validator.add(registerForm.userName,'minLength:2',' User name cannot be less than 2 Bit ')

But the problem comes with it: We changed the validation rule for user names from "can't be empty" to "can't be less than two digits", so we can't verify whether it is empty or not.

Can you customize multiple verification rules like element-ui1? It's like this:


validator.add(registerForm.userName,[{
	strategy:'isNoneEmpty',
	errorMsg:' User name cannot be empty '
},{
	strategy:'minLength:2',
	errorMsg:' User name length cannot be less than 2 Bit '
}])

Now that "rule" is in the form of array-object, we need to change the add function to 1:


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)
	}
}

Advantages of policy mode:

Using combination, delegation, polymorphism and other technologies and ideas, we can effectively avoid multiple conditional selection statements (about this point, the author made a detailed explanation in this article); Perfect implementation of the design pattern should have the "open-closed" principle, most of the rules based on the policy pattern are easy to expand, easy to use to avoid a lot of CV work


Related articles: