美文网首页
更优雅的表单校验(策略模式)

更优雅的表单校验(策略模式)

作者: 一方天地sq | 来源:发表于2017-06-21 23:47 被阅读0次

    在任何一个web项目中,都离不开表单的提交,而表达提交有离不来各种数据校验,那么,有没有一种更好的写法可以是使表达校验变得已于维护。
    看一下代码

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <form action="" id="registerForm" method="post">
        <div>
            请输入用户名:
            <input type="text" name="userName">
        </div>
        <div>
            请输入密码:
            <input type="text" name="password">
        </div>
        <div>
            请输入手机号:
            <input type="text" name="phoneNumber">
        </div>
        <button>提交</button>
    </form>
    </body>
    <script>
        var registerForm =document.getElementById('registerForm')
        registerForm.onsubmit = function () {
            if(registerForm.username.value === ''){
                alert('用户名不能为空')
            }
            if(registerForm.password.value === ''){
                alert('密码不能为空')
            }
            if(!/(^1[3|5|8][0-9]{9}$)/.text(registerForm.phoneNumber.value)){
                alert('手机号格式不正确')
            }
        }
    </script>
    </html>
    

    这是一种常见的编码方式,但是却缺点也显而易见,
    1,onsubmit函数过于庞大,并且包含过多的if分支,
    2,函数缺乏弹性如果要增加一个新的校验规则或者改变密码长度校验都必须修改onsubmit内部实现,违反了开放封闭原则
    3,复用性差,如果另外一个表单,也需要进行一些类似的校验,那么这些校验逻辑可能满天飞了。
    上面的问题我们可以使用策略模式来进行一步步的优化。那什么是策略模式呢?策略模式的定义是:定义一系列的算法,把他们一个个封装起来,并且使他们可以相互转换 。策略模式的作用就是将算法的使用与算法的实现分离开来。

    重构表单校验

    使用策略模式重构表单的第一步就是把校验逻辑封装成策略类,代码如下

         isNonEmpty: function (value , errorMsg) {
               if(value === ''){
                   return errorMsg
               }
            },
            minLength: function (value,,length,errorMsg) {
                if(value.length<length){
                    return errorMsg
                }
            },
            isMoblie: function (value,errorMsg) {
                if(!/(^1[3|5|8][0-9]{9}$)/.text(registerForm.phoneNumber.value){
                  return errorMsg
                }
            }
        }
    

    封装完之后的下一步该如何继续呢?我们最终的目的是不修改onsubmit的方法来实现校验的添加,所以我们可以增加一个中间方法用来连接submit和校验。代码如下

     var strategies = {
            isNonEmpty: function (value , errorMsg) {
               if(value === ''){
                   return errorMsg
               }
            },
            minLength: function (value,,length,errorMsg) {
                if(value.length<length){
                    return errorMsg
                }
            },
            isMoblie: function (value,errorMsg) {
                if(!/(^1[3|5|8][0-9]{9}$)/.text(registerForm.phoneNumber.value)){
                  return errorMsg
                }
            }
        }
        var registerForm =document.getElementById('registerForm');
        var vaildateFunc =function () {
            var vaildator = new Validator();
            vaildator.add(registerForm.userName,'isNonEmpty','用户名不能为空')
            vaildator.add(registerForm.password,'minLength:6','密码不能小于6位')
            vaildator.add(registerForm.phoneNumber,'isMoblie','请输入正确的手机号')
            var errorMsg = vaildator.start();
            return errorMsg
        }
        registerForm.onsubmit = function () {
           var errorMsg = vaildateFunc();
           if(errorMsg){
               alert(errorMsg)
               return false
           }
        }
    
    

    上面的代码增加了vaildateFunc方法并且增加了一个Validator类来验证校验,下面是Validator的验证方法

     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)
            })
            
        };
        Validator.prototype.start = function () {
            console.log(this.cache);
            for(var i= 0,vaildateFunc;vaildateFunc = this.cache[i++];){
                var msg = vaildateFunc();
                if(msg){
                    alert(msg);
                    return false
                }
            }
        }
    

    现在我们在改写某个规则的时候就只需要编写或改写少量代码,例如用户名长度改为不少于四个字符

    vaildator.add(registerForm.password,'minLength:6','密码不能小于6位')
    改为
    vaildator.add(registerForm.password,'minLength:4','密码不能小于4位')

    =====================================================

    突然有一天项目经理要求你既要校验用户名不能为空,又不能小于6位数字上面的代码就又不适用了,所以我们还需要继续改进一下。
    调用代码的时候参数改为数组,代码如下

    var vaildateFunc = function () {
            var vaildator = new Validator();
            vaildator.add(registerForm.userName, [{
                strategy:'isNonEmpty',
                errorMsg:'用户名不能为空'
            }, {
                    strategy:'minLength:6',
                    errorMsg:'用户名长度不能小于6位'
                }
            ])
            vaildator.add(registerForm.password,[{
                strategy:'minLength:6',
                errorMsg:'密码能小于6位'
            }])
            vaildator.add(registerForm.phoneNumber,[{
                strategy:'isMoblie',
                errorMsg:'请输入正确的手机号'
            }])
            var errorMsg = vaildator.start();
            return errorMsg
        };
     Validator.prototype.add = function (dom, rules) {
            var self = this;
            console.log(rules)
            for(var i =0,rule;rule = rules[i++];){
                (function (rule) {
                    try{
                        var ary = rule.strategy.split(':');
                        self.cache.push(function () {
                            var strategy = ary.shift();
                            ary.unshift(dom.value);
                            ary.push(rule.errorMsg);
                            return  strategies[strategy].apply(dom,ary)
                        })
                    }catch (e){
                        console.log(e)
                    }finally {
                        console.log(232323)
                    }
    
                })(rule)
            }
    
    
        };
    

    上面的代码已经可以进行2次校验了。
    从这个例子我们不难看出这种方式的一些优点,
    1,可以有效避免多重条件选择语句
    2,可以复用
    当然也会有些缺点比如会出现很多类和对象,但是相对写道方法里面要好

    相关文章

      网友评论

          本文标题:更优雅的表单校验(策略模式)

          本文链接:https://www.haomeiwen.com/subject/rcmtcxtx.html