JS使用策略模式改写表单验证

原始验证

现在我们有一个表单:

<form action="/" id="myForm" method="POST">
    用户名:<input name='user' type="text"> 
    密 码 :<input name='pwd' type="text"> 
    <button type="submit" name='btn'>提交表单</button>
</form>

我们要做表单验证,那么常见的写法是下面这种if  else分支处理

<script>
    var form = document.getElementById('myForm');
    form.btn.onclick = function(e) {
        var userVal = form.user.value;
        var pwdVal = form.pwd.value;

        if (!userVal) {
            console.log('用户名不能为空');
            return false;
        }

        if (!pwdVal || (pwdVal.length <= 6)) {
            console.log('密码长度必须大于6位');
            return false;
        }

        console.log('提交成功');
        return false;
    }
</script>

但是这种写法有个很大的缺点,就是不具备扩展性。如果要多一个手机号的验证,那么就要加多一个else分支做业务处理。而且写完的验证也没办法应用到别的表单上,十分不方便。

使用策略模式验证

为了可以实现动态认证,并且提高代码扩展性,我们可以采用策略模式来改写表单验证

第一步:定义策略对象

//策略对象
    var strategy = {
        require: function(val, msg) {
            if (!val) {
                return msg
            }
        },
        min: function(val, length, msg) {
            if (!val || (val.length <= 6)) {
                return msg
            }
        },
        phone: function(val, msg) {
            let patt = /^1[3-9]\d{9}$/
            let flag = patt.test(val)
            if (!flag) {
                return msg
            }
        }
    }

定义策略对象的目的是抽象、封装每个验证算法的业务逻辑。每添加一种验证,其实就是新增一种策略而已,可直接在策略对象中添加新方法,方便扩展。抽象是为了能让方法能适应多更的应用场景,比如min方法中的length可以指定任意长度的字符。

第二部:定义策略类

//策略类
    var Validate = function() {
        this.rules = []

        this.add = function(dom, rule, msg) {
            let args = rule.split(':')
            let func = args.shift();
            args.push(msg)
            args.unshift(dom.value)

            let obj = {
                func,
                args
            }
            this.rules.push(obj)
                //strategy[func]
        }

        this.check = function() {
            var errors = []
            for (var i = 0; i < this.rules.length; i++) {
                var error = strategy[this.rules[i].func].apply(strategy, this.rules[i].args) //调用策略对象中的方法
                if (error) {
                    errors.push(error)
                }
            }
            return errors
        }
    }

我们定义了一个rules属性,一个add方法,一个check方法。rules属性是记录add方法中增加的验证规则,check方法是将rules中的验证规则循环调用策略对象中的方法。这样一来可以实现策略对象的高可用。

调用

    function checkForm() {
        var validate = new Validate()
        validate.add(form.user, 'require', '用户名必须填写')
        validate.add(form.pwd, 'min:6', '密码长度必须大于6位')
        var res = validate.check()

        if (res.length) {
            console.log(res)
        } else {
            console.log('验证成功')
        }

        return false;
    }
    var form = document.getElementById('myForm')
    form.btn.onclick = checkForm

可见,使用策略模式之后,调用验证变得十分简洁。而且还可用于其他文件,完全可以将其封装成类库来使用。

完整代码:

    //策略对象
    var strategy = {
        require: function(val, msg) {
            if (!val) {
                return msg
            }
        },
        min: function(val, length, msg) {
            if (!val || (val.length <= 6)) {
                return msg
            }
        },
        
    }

    //策略类
    var Validate = function() {
        this.rules = []

        this.add = function(dom, rule, msg) {
            let args = rule.split(':')
            let func = args.shift();
            args.push(msg)
            args.unshift(dom.value)

            let obj = {
                func,
                args
            }
            this.rules.push(obj)
                //strategy[func]
        }

        this.check = function() {
            var errors = []
            for (var i = 0; i < this.rules.length; i++) {
                var error = strategy[this.rules[i].func].apply(strategy, this.rules[i].args) //调用策略对象中的方法
                if (error) {
                    errors.push(error)
                }
            }
            return errors
        }
    }
    //调用
    function checkForm() {
        var validate = new Validate()
        validate.add(form.user, 'require', '用户名必须填写')
        validate.add(form.pwd, 'min:6', '密码长度必须大于6位')
        var res = validate.check()

        if (res.length) {
            console.log(res)
        } else {
            console.log('验证成功')
        }

        return false;
    }
    var form = document.getElementById('myForm')
    form.btn.onclick = checkForm

我们再来看看扩展性如何。如果我们要多添加一条手机号的,那么只需要在策略对象中添加相应的方法即可:

成功运行。

可以看到改写后的代码扩展性也不错,而且使用起来更加简单方便。

总结

在某些分支众多,业务逻辑需要频繁if else判断的场景下,可以考虑抽象封装策略模式来完成工作任务,使得代码更加容易扩展,适用性更强

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值