用策略模式实现表单的校验

2017-08-09  本文已影响0人  SiHao24

预览

GIF.gif

作为一名前端人士,在一个web项目中,注册、登录、修改用户信息等功能的实现都离不开表单。在将用户输入的数据提交给后台之前,常常需要做一些客户端力所能及的校验工作。比如注册的时候需要校验是否填写了用户名,密码的长度是否符合规定,等等。好了,您可能会说,说出你的梦想,开始你的表演,接下来我要开始我的表演了。😜
假设现在我要写一个注册页面,在店家注册按钮之前,有如下几条校验逻辑:
用户名不能为空
密码长度不能小于6位
手机号码必须符合格式

一、表单校验的第一个版本

<html>
<body>
    <form action="https://www.baidu.com" method="post" id="registerForm">
        请输入用户名<input type="text" name="userName"><br> 
        请输入密码  <input type="password" name="password"><br> 
        请输入手机号码<input type="text" name="phoneNumber"><br>
        <button>提交</button>
    </form>
</body>
</html>

么有写CSS样式,感觉界面丑哭😭,实现功能最重要,对不?

    <script>
        const registerForm = document.getElementById('registerForm');
        registerForm.onsubmit = function() {
            if (registerForm.userName != "") {
                if (registerForm.password.length >= 6) {
                    if (/^1[3|4|5|7|8][0-9]{9}$/.test(registerForm.phoneNumber)) {
                        alert('成功');
                    } else {
                        alert('请输入正确的的手机号!');
                        return false;
                    }
                } else {
                    alert('密码不能小于六位');
                    return false;
                }
            } else {
                alert("用户名不能为空!");
                return false;
            }
        }
    </script>

这是一种最常见的代码编写方式,但是他的缺点显而易见。registerForm.onsubmit函数比较庞大,包含了过多的if-else语句,如果增加一条新的校验规则,或者想把免得长度校验从6位增加到8位,要去registerForm.onsubmit内部更改,这样就违反了开放-封闭的原则。

二、用策略模式实现表单的校验

我们经常说,条条大路通罗马,在现实生活中,很多时候也有很多途径到达同一个目的地。假如我们要去某个地方旅游,我们可以这样选择:
不考虑金钱的情况下,为了节省时间,我们选择乘坐飞机
考虑钱的话,那就火车或者bus
像我这样的只能来个自行车去旅游了,这就是差距啊😭,到此为止,我们来说说主角吧,蹬蹬蹬蹬,策略模式来了。
策略模式就是定义一系列算法,把它们一个个封装起来,并且是它们可以相互替换。
用策略模式来实现表单的检验,第一步我们先来把这些校验逻辑封装成策略对象

  var strategies = {
    // errorMsg参数,提升了适用性
    isNonEmpty: function(value, errorMsg) {  //不为空
        if (value === '') {
            // 返回字符串true  错误信息
            return errorMsg;
        }
    },
    minLength: function(value, length, errorMsg) { //限制最小长度
        if (value.length < length) {
            return errorMsg;
        }
    },
    isMobile: function(value, errorMsg) {
        if (!/^1[1|5|8|7|4|3][0-9]{9}$/.test(value)) { //电话号码校验
            return errorMsg;
        }
    }
}

接下来就是实现Validator类了。Validator负责接收用户的请求并委托给strategy对象。我们先来了解下用户是如何向Validator类发送请求的,这有助于我们知道如何去编写Validator类的代码。代码如下:

        function validateFunc() {
            // 校验处理 分离出去
            var validator = new Validator(); //创建validator对象
            // 一个个去校验
            // 数组 遍历
            /**********************添加校验规则**********************/
            validator.add(registerForm.userName, 'isNonEmpty', '用户名不能为空');
            validator.add(registerForm.password, 'minLength:6', '密码长度不能少于6位');
            validator.add(registerForm.phoneNumber, 'isMobile', '手机号码格式不正确')
            var errorMsg = validator.start(); //获取校验结果
            // 一个个去校验
            return errorMsg; //返回校验结果
        }
        registerForm.onsubmit = function() {
            // 一票规则 数组
            var errorMsg = validateFunc(); //如果errorMsg有确切的返回值,说明校验未通过,即输入的内容不符合规则
            if (errorMsg) {
                alert(errorMsg);
                return false; //阻止表单提交
            }
        }

通过这段代码,我们先创建了一个validator对象,然后通过validator.add方法,往validator对象中添加一些检验规则。validator.add方法接受三个参数,

  validator.add(registerForm.password, 'minLength:6', '密码长度不能少于6位');

registerForm.password为参与校验的input输入框。
'minLength:6'是一个以冒号隔开的字符串。冒号前面的minLength代表挑选的strategy对象,冒号后面的数字6表示在校验中过程中所必须的参数。'minLength:6'的意思是校验registerForm.password这个文本框输入的最小长度不能小于6。如果这个字符串中不过不包含冒号,说明教研过程中不需要额外的参数,如'isNonEmpty'&'isMobile'。
第三个参数是当被校验的值不符合规则的时,返回的错误信息。
在往validator对象里添加了一系列的校验规则后,我们就要使用validator.start()方法来启动校验。如果validator.start()返回一个确切的errorMsg字符串当作返回值,就表明校验没有通过,此时需要registerForm.onsubmit方法返回false来阻止表单的提交。
最后实现Validator类:

  var Validator = function() {
    this.cache = [];
}

Validator.prototype.add = function(ele, rule, errorMsg) {
    var arr = rule.split(':');
    this.cache.push(function() {
        // 规则
        var strategy = arr.shift();
        arr.unshift(ele.value);
        arr.push(errorMsg);
        return strategies[strategy].apply(ele, arr);
    });
}

Validator.prototype.start = function() {
    for (var i = 0, validatorFunc; validatorFunc = this.cache[i++];) {
        var msg = validatorFunc();
        if (msg) {
            return msg;
        }
    }
};

使用策略模式重构代码后,仅仅可以通过“配置”的方式就可以完成一个表单的校验,这些校验规则也可以复用在程序的任何地方,这就是我们所所得,处处适用。
在修改某个校验规则的时候,只需要编写或者改写少量的代码。假如想将用户名输入框的校验规则修改成用户名不能少于四个字符。代码如下所示:

  validator.add(registerForm.userName, 'isNonEmpty', '用户名不能为空');
//改成
validator.add(registerForm.userName, 'minLength:8', '用户名长度不能小于8位');

学习中遇到的问题

(1)什么鬼?在校验失败的情况下,还会实现页面的跳转,真的让人有点受不了,所以我要说的是,一定要在registerForm.onsubmit方法返回false来阻止表单的提交。
(2)再来解释下手机号码的校验规则

      isMobile: function(value, errorMsg) {
        if (!/^1[1|3|4|5|7|8][0-9]{9}$/.test(value)) { //电话号码校验
            return errorMsg;
        }
    }

表示第一位只匹配数字1,第二位匹配(3|4|5|7|8)里面的任意一个数值,剩下的9位是没有限制的,也就是可以匹配0-9之间的任意数字,最后以$结尾。test函数返回的是一个boolean值。正则表达式中 test、exec、match 方法区别http://www.cnblogs.com/meixianfeng/articles/2762273.html
代码地址:https://github.com/SiHao24/js_pattern

结语

策略模式的巧妙之处远远不止这些,我只是列举了其中小小的一个环节!还需要花费更多的时间去学习其中的奥秘。虽然开始学的很艰难,但是努力过后,就会陶醉在知识的海洋里!
有建议或者觉得有错误的地方可以指出来哟,让我跟随大佬们的步伐,继续努力吧!

上一篇 下一篇

猜你喜欢

热点阅读