利用策略模式实现表单验证

普通表单验证

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

缺点:

  • registerForm.onsubmit 函数比较庞大,包含了很多 if-else 语句,这些语句需要覆盖所有
    的校验规则。
  • registerForm.onsubmit 函数缺乏弹性,如果增加了一种新的校验规则,或者想把密码的长 度校验从 6 改成8,我们都必须深入 registerForm.onsubmit 函数的内部实现,这是违反开 放—封闭原则的。
  • 算法的复用性差,如果在程序中增加了另外一个表单,这个表单也需要进行一些类似的 校验,那我们很可能将这些校验逻辑复制得漫天遍野。

使用策略模式重构

策略模式指的是定义一系列的算法,把它们一个个封装起来。将不变的部分和变化的部分隔开是每个设计模式的主题,策略模式也不例外,策略模式的目的就是将算法的使用与算法的实现分离开来。

首先我们将校验逻辑封装成对象

var strategies = {
        isNonEmpty: 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;
            }
        }
    }

实现Validator函数

Validator其实就是将要验证的表单添加进去,然后进行校验,所以我们定义一个函数
存贮表单验证的函数,进行验证即可
	//创建一个函数
	var Validator = function(){
        this.cache = []; // 保存校验规则
    };
     /**
     * add 
     * dom  dom节点
     * rule:部分参数要求长度或者其他参数
     * errorMsg:错误返回值
     * */
    Validator.prototype.add = function( dom, rule, errorMsg ){
   //将有参数的数据分开 如 minLength:6  ===> [minLength,6] 么有的话就是一数组  [minLength]
        var ary = rule.split( ':' );
        //把校验的步骤用空函数包装起来,并且放入 cache
        this.cache.push(function(){
          //拿到当前要执行的函数名称
            var strategy = ary.shift();
            //拿到dom的值存到数组开头
            ary.unshift( dom.value ); 
           // 把 errorMsg 添加进参数列表
            ary.push( errorMsg );
            // 等待执行
            return strategies[ strategy ].apply( dom, ary );
        });
    };
    /**
     * 执行验证
     * 按顺序执行cache函数
     * */
    Validator.prototype.start = function(){
        for ( var i = 0, validatorFunc; validatorFunc = this.cache[ i++ ]; ){
            var msg = validatorFunc(); // 开始校验,并取得校验后的返回信息
            if ( msg ){ // 如果有确切的返回值,说明校验没有通过
                return msg;
            }
        }
    };

以上我们实现了校验函数的添加和验证

调用表单验证类

// Validator类
    var validataFunc = function () {
        var validator = new Validator() //创建一个 validator 对象3
         //创建校验规则
        validator.add( registerForm.userName, 'isNonEmpty', '用户名不能为空' );
        validator.add( registerForm.password, 'minLength:6', '密码长度不能少于 6 位' );
        validator.add( registerForm.phoneNumber, 'isMobile', '手机号码格式不正确' );
        var errorMsg = validator.start(); // 获得校验结果
        return errorMsg; // 返回校验结果
    }
    var registerForm = document.getElementById( 'registerForm' );
    registerForm.onsubmit = function(){
        var errorMsg = validataFunc(); // 如果 errorMsg 有确切的返回值,说明未通过校验
        if ( errorMsg ){
            alert ( errorMsg );
            return false; // 阻止表单提交
        }
    };

完整代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="http:// xxx.com/register" id="registerForm" method="post">
    请输入用户名:<input type="text" name="userName"/>
    请输入密码:<input type="text" name="password"/>
    请输入手机号码:<input type="text" name="phoneNumber"/>
    <button>提交</button>
</form>
<script>
    /**策略模式重构表单验证*/
    //逻辑验证封装成对象
    var strategies = {
        isNonEmpty: 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;
            }
        }
    }
    // Validator类
    var validataFunc = function () {
        var validator = new Validator() //创建一个 validator 对象3
         //创建校验规则
        validator.add( registerForm.userName, 'isNonEmpty', '用户名不能为空' );
        validator.add( registerForm.password, 'minLength:6', '密码长度不能少于 6 位' );
        validator.add( registerForm.phoneNumber, 'isMobile', '手机号码格式不正确' );
        var errorMsg = validator.start(); // 获得校验结果
        return errorMsg; // 返回校验结果
    }
    var registerForm = document.getElementById( 'registerForm' );
    registerForm.onsubmit = function(){
        var errorMsg = validataFunc(); // 如果 errorMsg 有确切的返回值,说明未通过校验
        if ( errorMsg ){
            alert ( errorMsg );
            return false; // 阻止表单提交
        }
    };
    var Validator = function(){
        this.cache = []; // 保存校验规则
    };
    /**
     * 添加要验证的信息
     * dom  dom节点
     * rule:部分参数要求长度
     * errorMsg:错误返回值
     * */
    Validator.prototype.add = function( dom, rule, errorMsg ){
        //将有参数的数据分开 如 minLength:6  ===> [minLength,6] 么有的话就是一数组  [minLength]
        var ary = rule.split( ':' );
        //把校验的步骤用空函数包装起来,并且放入 cache
        this.cache.push(function(){
          //拿到当前要执行的函数名称
            var strategy = ary.shift();
            //拿到dom的值存到数组开头
            ary.unshift( dom.value );
            // 把 errorMsg 添加进参数列表
            ary.push( errorMsg );
            // 等待执行
            return strategies[ strategy ].apply( dom, ary );
        });
    };
    /**
     * 执行验证
     * 按顺序执行cache函数
     * */
    Validator.prototype.start = function(){
        for ( var i = 0, validatorFunc; validatorFunc = this.cache[ i++ ]; ){
            var msg = validatorFunc(); // 开始校验,并取得校验后的返回信息
            if ( msg ){ // 如果有确切的返回值,说明校验没有通过
                return msg;
            }
        }
    };
</script>
</body>
</html>





上一篇:异常 | 求你别再写满屏的try-catch了,用全局异常好吗?- 夹私货-行测


下一篇:go学习笔记-day20