用策略模式重构表单校验「原生js加强你的js代码逻辑」。

在一个 Web 项目中,注册、登录、修改用户信息等功能的实现都离不开提交表单。

在将用户输入的数据交给后台之前,常常要做一些客户端力所能及的校验工作,比如注册的
时候需要校验是否填写了用户名,密码的长度是否符合规定,等等。这样可以避免因为提交不合法数据而带来的不必要网络开销。
主要解决了很多 冗余的 if-else 语句,提高了代码的复用性。

第一版:简单版本

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <form id="registerForm" method="POSt">
        请输入用户名:<input type="text" id="userName">
        请输入密码:<input type="text" id="password">
        请输入手机号:<input type="text" id="phoneNumber">
    </form>
    <button id="button">提交</button>
</body>
<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 (!/^(?:(?:\+|00)86)?1(?:(?:3[\d])|(?:4[5-79])|(?:5[0-35-9])|(?:6[5-7])|(?:7[0-8])|(?:8[\d])|(?:9[1589]))\d{8}$/.test(value)) {
                return errorMsg;
            }
        }
    };

    class Validator {
        constructor() {
           this.arr = []
        }
        add(dom,rule,errorMsg) {
            let ary = rule.split(':')
            // 将每个 add 检验函数添加数组中进行统一执行
            this.arr.push(function ()  {
                // 按照 : 分割minLength参数 并且取出方法名字
                let firstParams = ary.shift()
                // 将表单的值追加第一个,对应校验方法的第一个参数
                ary.unshift(dom.value)
                // 将错误信息放到末尾
                ary.push(errorMsg)
                 /**
                  * 这里使用apply就是为了在下面使用add 方法的时候进行调用并且传参数,并且修改了this指向,指向当前的输入框。第二的参数传入的一个数组,在上面的校验函数
                  * 每个参数就对应传进来的数组下标。
                  */ 
                return strategies[firstParams].apply(dom,ary)
            })
        }
        start() {
            // 统一执行校验方法并返回校验错误的信息。
            for(let i = 0,validataFunc;validataFunc = this.arr[i++];) {
                 var msg = validataFunc()
                 if(msg) {
                     return msg
                 }
            }
        }
    }


    let registerForm = document.getElementById('registerForm');
    button.onclick =  function () {
        var validator = new Validator(); // 创建一个 validator 对象
        console.log(registerForm.userName);
        validator.add(registerForm.userName, 'isNonEmpty', '用户名不能为空');
        validator.add(registerForm.password, 'minLength:6', '密码长度不能少于 6 位');
        validator.add(registerForm.phoneNumber, 'isMobile', '手机号码格式不正确');
        var errorMsg = validator.start(); // 获得校验结果
        if (errorMsg) {
            alert(errorMsg);
            return false; // 阻止表单提交
        }
        alert('通过校验')
    };

  


</script>

</html>

第二版本基于函数扩展校验。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <form id="registerForm" method="POSt">
        请输入用户名:<input type="text" id="userName">
        请输入密码:<input type="text" id="password">
        请输入手机号:<input type="text" id="phoneNumber">
    </form>
    <button id="button">提交</button>
</body>
<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 (!/^(?:(?:\+|00)86)?1(?:(?:3[\d])|(?:4[5-79])|(?:5[0-35-9])|(?:6[5-7])|(?:7[0-8])|(?:8[\d])|(?:9[1589]))\d{8}$/.test(value)) {
                return errorMsg;
            }
        }
    };


    class Validator {
        constructor() {
            this.arr = []
        }
        add(dom, rules,callBacks =[]) {
            // 如果有自定义的校验循环并执行
            if(callBacks.length) {
                for (let i = 0, callBack; callBack = callBacks[i++];) {
                    // 如果想再在 start 函数中再次调用 arr 中的函数就必须,定义一个函数追加进去,然后返回一个基于 apply 调用的新函数方便二次执行。
                      this.arr.push(function() {
                          return callBack.apply(dom,[dom.value])
                      })
                }
            }
            for (let i = 0, rule; rule = rules[i++];) {
                let ary  = rule.filed.split(':')
                // 将每个 add 检验函数添加数组中进行统一执行
                this.arr.push(function () {
                    // 按照 : 分割minLength参数 并且取出方法名字
                    let firstParams = ary.shift()
                    // 将表单的值追加第一个,对应校验方法的第一个参数
                    ary.unshift(dom.value)
                    // 将错误信息放到末尾
                    ary.push(rule.errMsg)
                    /**
                     * 这里使用apply就是为了在下面使用add 方法的时候进行调用并且传参数,并且修改了this指向,指向当前的输入框。第二的参数传入的一个数组,在上面的校验函数
                     * 每个参数就对应传进来的数组下标。
                     */
                    return strategies[firstParams].apply(dom, ary)
                })
            }
        }
        start() {
            // 统一执行校验方法并返回校验错误的信息。
            for (let i = 0, validataFunc; validataFunc = this.arr[i++];) {
                var msg = validataFunc()
                if (msg) {
                    return msg
                }
            }
        }
    }
    let formValidate = function () {
        var validator = new Validator(); // 创建一个 validator 对象
        console.log(registerForm.userName);
        validator.add(registerForm.userName, [{
            filed: 'isNonEmpty',
            errMsg: '用户名不能为空'
        }, {
            filed: 'minLength:6',
            errMsg: '用户名长度不能少于 6 位'
        }]);

        validator.add(registerForm.password, [{
            filed: 'minLength:6',
            errMsg: '密码长度不能少于 6 位'
        }],[
            function (value) {
                console.log(this,'当前元素'); // 必须是 function 写法,箭头函数直接指向上一级,Window
                if(value.length >= 14) {
                    return '密码长度不能大于 14 位'
                }
            }
        ]);

        validator.add(
         registerForm.phoneNumber,
         [{
            filed: 'isMobile',
            errMsg: '手机号码格式不正确'
        }],
        [
            (value) => {
              if(value.length >= 12) {
                 return '手机号不能大于 12 位'
              }
           },
           (value) => {
              if(value == '') {
                 return '手机号不能为空'
              }
           },
        ]
        );
        return validator.start(); // 获得校验结果
    }

    button.onclick = function () {
        let errorMsg = formValidate()
        if (errorMsg) {
            alert(errorMsg);
            return false; // 阻止表单提交
        }
        alert('通过校验')
    };



</script>

</html>

猜你喜欢

转载自blog.csdn.net/qq_54753561/article/details/130018780