策略模式
根据不同参数可以命中不同的策略
const strategy = {
'S': function(salary) {
return salary * 4
},
'A': function(salary) {
return salary * 3
},
'B': function(salary) {
return salary * 2
}
}
const calculateBonus = function(level, salary) {
return strategy[level](salary)
}
calculateBonus('A', 10000) // 30000
在函数是一等公民的 JS 中, 策略模式的使用常常隐藏在高阶函数中, 稍微变换下上述 demo 的形式如下, 可以发现我们平时已经在使用它了, 恭喜我们又掌握了一种设计模式。
return salary * 4
}
const A = function(salary) {
return salary * 3
}
const B = function(salary) {
return salary * 2
}
const calculateBonus = function(func, salary) {
return func(salary)
}
calculateBonus(A, 10000) // 30000
在一个Web项目中,注册,登录,修改用户信息,下订单等功能的实现都离不开提交表单.
假设我们正在编写一个注册的页面,在点击注册按钮之前,有如下几条校验逻辑。
所有选项不能为空
用户名长度不能少于6位
密码长度不能少于6位
手机号码必须符合格式
邮箱地址必须符合格式
HTML代码:
<body>
<form action="http://www.baidu/register" id="registerForm" method="post" onsubmit=" return check()">
<div class="form-group">
<label for="user">请输入用户名:</label>
<input type="text" class="form-control" id="user" name="userName">
</div>
<div class="form-group">
<label for="pwd">请输入密码:</label>
<input type="password" class="form-control" id="pwd" name="passWord">
</div>
<div class="form-group">
<label for="phone">请输入手机号码:</label>
<input type="tel" class="form-control" id="phone" name="phoneNumber">
</div>
<div class="form-group">
<label for="email">请输入邮箱:</label>
<input type="text" class="form-control" id="email" name="emailAddress">
</div>
<input type="submit" id="submit" value="提交">
</form>
</body>
一般情况下的JavaScript代码:
<script>
let registerForm = document.querySelector('#registerForm')
function check(){
if(registerForm.userName.value === ''){
alert('用户名不能为空!')
return false
}
if(registerForm.userName.value.length<6){
alert('用户名长度不能少于6位!')
return false
}
if(registerForm.passWord.value===''){
alert('密码不能为空!')
return false
}
if(registerForm.passWord.value.length<6){
alert('密码长度不能少于6位!')
return false
}
if(registerForm.phoneNumber.value===''){
alert('手机号码不能为空!')
return false
}
if(!/^1(3|5|7|8|9)[0-9]{9}$/.test(registerForm.phoneNumber.value)){
alert('手机号码格式不正确')
return false
}
if(registerForm.emailAddress.value===''){
alert('邮箱地址不能为空!')
return false
}
if(!/^\w+([+-.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/.test(registerForm.emailAddress.value)){
alert('邮箱地址格式不对')
return false
}
}
</script>
策略模式
使用
// 获取表单form元素
var form = document.getElementById('f1');
// 创建表单校验实例
var validation = new Formvalidation(VerifiPolicy);
// 编写校验配置
validation.add(form.username, 'isNoEmpty', '用户名不能为空');
validation.add(form.password, 'minLength: 6', '密码长度不能小于6个字符');
validation.add(form.code, 'isMobile', '请填写正确的手机号');
// 开始校验,并接收错误信息
var errorMsg = validation.start();
// 如果有错误信息输出,说明校验未通过
if(errorMsg){
// 做一些其他的事
return false;
}
编写环境类
// 构造函数
var Formvalidation = function(VerifiPolicy){
// 保存策略对象
this.strategies = VerifiPolicy;
// 验证缓存
this.validationFns = [];
}
// add 方法 add方法第一个参数,是要验证的表单元素,第二个参数是一个字符串,使用 冒号(:) //分割,前面是策略方法名称,后面是传给这个方法的参数,第三个参数仍然是错误信息,
Formvalidation.prototype.add = function(dom, rule, errorMsg){
var ary = rule.split(':');
var arg = [];
var self = this;
this.validationFns.push(function(){
arg = []; // 重置参数
var ruleName = ary[0]; // 策略对象方法名
// 组装参数
arg.push(dom.value);
if(ary[1]){
arg.push(ary[1]);
}
arg.push(errorMsg);
// 调用策略函数
return self.strategies[ruleName].apply(dom, arg);
});
}
// 开始验证
Formvalidation.prototype.start = function(){
for(var i = 0; ; i++){
var msg = this.validationFns[i]();
if(msg){
return msg;
}
}
}
编写策略类
// 策略对象
var VerifiPolicy = {
// 判断是否为空
isNoEmpty : 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;
}
}
// 其他
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。