前端开发js验证插件

前端开发短信验证码怎么做?|前端程序开发|手机端前端开发

流行的js验证库现在也出现过不少,个人都没怎么用的习惯的,决定自己手写一个,希望各位轻喷
话不多少,进入正题,文章有点长,请耐心看完。

校验的话无非就是未元素绑定事件,事件触发之后触发回调处理
我们用场景来说话哈。

场景1、登录
ps. 只是对用户名密码进行校验,首先为用户名绑定事件(比较普遍blur, keyup)
javascript 代码

var _ = function (id) {
    return document.getElementById(id);
}
var EventListener = function (obj, type, handle) {
    try { // Chrome、FireFox、Opera、Safari、IE9.0及其以上版本
        obj.addEventListener(type, handle, false);
    } catch (e) {
        try { // IE8.0及其以下版本
            obj.attachEvent(‘on’ + type, handle);
        } catch (e) { // 早期浏览器
            obj[‘on’ + type] = handle;
        }
    }
}
var validator = {
    checkUserName: function () {
        EventListener(_(‘#userName’), “blur”, function (event) {
            //Todo
            //校验数据是否准确
        })
    }
}

以上确实可以做到校验了,但是我们提交订单的时候也需要做一次整体的校验,因此我需要循环每一个输入框的校验规则来判断是否数据合理,上面的代码很明显就满足不了需求了。

那我们现在需要设计下代码了,代码应该分两部分,一个是单个校验的校验器,一部分是整个校验的管理器(负责管理所有校验器),所以就有以下的代码
javascript 代码

var extend = function(){
//Todo
//这里面暂不实现了,千篇一律
}
var validator = function(opt){
//Todo
// 暂时不写实现
}
validator.prototype = {
}
//所有子校验的管理器
var validatorManager = function(){
}

对上述代码,其实大家试着初始化就会知道,其实这段代码不好初始化,管理器要初始化N个表单元素的初始化,那传递给validatorManager的参数不就一大推吗?
javascript 代码

new validatorManager([{
        el: xxx,
        events: [],
        callback: fn
    },
    {
        el: xxx,
        events: [],
        callback: fn
    },
    {
        el: xxx,
        events: [],
        callback: fn
    },
    {
        el: xxx,
        events: [],
        callback: fn
    },
    {
        el: xxx,
        events: [],
        callback: fn
    }
])

我艹,这立马咋写的,万一有一个N个字段的表单,那我初始化不就得完了
对于这个管理器,懒人的想法是,我要是只要传form表单元素进去,自动给我做完所有的事情那就perfect了。ok, 我们就朝着这个方向走

假设我只需要传递form表单元素, 那我们要达成校验,需要做几步事情
[ol]
[li]1、怎么获取要校验的元素[/li]
[li]2、怎么判断元素的校验规则是什么[/li]
[/ol]

先说第一步,传一个表单元素,怎么获取校验的元素,那我们可以用document.querySelectorAll(“:input”),我们可以获取到所有的表单元素了
问题是: 假设我有些元素不需要校验,那咋办。

结合第二步的问题,那我们是不是可以尝试在需要校验的元素上面增加一些特殊的属性来标示呢,我就是这么想的,然后给元素都加了一个属性
html 代码

<!DOCTYPE html>
<html lang=”en”>
<head>
    <meta charset=”UTF-8″>
    <title>前端开发季度考核内容总结</title>
</head>
<body>
    <form action=””>
        <input type=”text” data-jvalidator>
    </form>
</body>
</html>

再说第二步,元素的校验规则。每一个元素的校验规则都不同,好难区分哦。不过回头看看刚刚的html,既然我们已经增加了属性了,但属性的值对应的是规则不就解决这个问题了吗?

html 代码

<!DOCTYPE html>
<html lang=”en”>
<head>
    <meta charset=”UTF-8″>
    <title>前端怎么开发</title>
</head>
<body>
    <form action=””>
        <input type=”text” data-jvalidator=”notEmpty”>
    </form>
</body>
</html>

到这里开发这个插件思路应该是明确了的,下面我就改下js代码
javascript 代码

var EventListener = function (obj, type, handle) {
    try { // Chrome、FireFox、Opera、Safari、IE9.0及其以上版本
        obj.addEventListener(type, handle, false);
    } catch (e) {
        try { // IE8.0及其以下版本
            obj.attachEvent(‘on’ + type, handle);
        } catch (e) { // 早期浏览器
            obj[‘on’ + type] = handle;
        }
    }
}
var PATTERN = []; //存放校验规则
var extend = function () {
    //Todo
    //这里面暂不实现了,千篇一律
}
var validator = function (opt) {}
validator.prototype = {
    //先暂时不写
}
var noop = function () {}
var validatorManager = function (formEl, opts) {}
validatorManager.prototype = {}

如上代码就是我们大体的一个校验框架了
现在剩下的问题是:
1、怎么给每一个元素添加校验规则,因为规则都是会变化的,不好写在这个共用的组件里面。
解决办法是:我们抽取出来一个公共的校验规则管理器,统计添加校验规则(策略者模式),这样子好处是:
a) 同一个规则不会重复添加
b) 规则管理维护成本低,一改全改
javascript 代码

validatorManager.PATTERN = [];
validatorManager.addPattern = function (pattern) {
    if (!pattern.name) {
        return;
    } //name就对应元素上的规则名
    validatorManager.PATTERN[pattern.name] = pattern;
}

现在似乎所有的问题都解决了,附上最终的代码
javascript 代码

var EventListener = function (obj, type, handle) {
    try { // Chrome、FireFox、Opera、Safari、IE9.0及其以上版本
        obj.addEventListener(type, handle, false);
    } catch (e) {
        try { // IE8.0及其以下版本
            obj.attachEvent(‘on’ + type, handle);
        } catch (e) { // 早期浏览器
            obj[‘on’ + type] = handle;
        }
    }
}
var PATTERN = []; //存放校验规则
var extend = function () {
    //Todo
    //这里面暂不实现了,千篇一律
}
var validator = function (opt) {
    this.opt = extend({
        el: null,
        events: []
    });
    this.el = this.opt.el;
    if (!el) {
        throw new Error(“校验规则需要有元素哦”);
    }
    this.__status = false;
    var pattern = this.el.getAttribute(“data-jvalidator”) || “”;
    this.pattern = pattern.replace(/\s+/g, ”).split(“&”);
    this.addEvent();
}
validator.prototype = {
    addEvent: function () {
        var events = this.opt.events || [];
        for (var i = events.length – 1; i > -1; i–) {
            EventListener(el, events[i], function (e) {
                //Todo 判断是否校验通过
                me.check();
            })
        }
    },
    check: function (callback) {
        var me = this;
        var value = this.el.value;
        var pattern = this.pattern;
        for (var i = 0, len = pattern.length; i < len; i++) {
            var ruleName = pattern[i];
            var realRule = PATTERN[ruleName];
            if (!realRule) {
                console.error(“不存在校验规则:” + pattern[i] + “,请确认后提交”);
            } else {
                realRule.callback.call(this.el, value, function (result) {
                    me.opts.on[result ? “valid” : “invalid”].call(me.el, PATTERN[ruleName]);
                    callback && callback(result);
                })
            }
        }
    }
}
var noop = function () {}
var validatorManager = function (formEl, opts) {
    this.opts = extend({
        evetns: [“keyup”, “blur”],
        on: {
            invalid: noop,
            valid: noop
        }
    }, opts || {})
    this.form = formEl;
    this.validators = []; //存放所有的子校验
    this.init();
}
validatorManager.prototype = {
    init: function () {
        var $el = this.form.querySelectorAll(“[data-jvalidator]”);
        var len = $el.length;
        if (len) {
            for (var i = 0; i < len; i++) {
                this.validators.push(new validator(extend({
                    el: $el[i]
                }, this.opts)));
            }
        }
    },
    /**
     * 校验整个表单全部时候填写正确
     * @param {Function} callback 执行完校验之后回调函数
     * @return {[type]} [description]
     */
    validatorAll: function (callback) {
        var isLegal = true;
        var validators = this.validators;
        var len = validators.length;
        for (var i = 0; i < len; i++) {
            (function (validator, index) {
                validator.check(function (result) {
                    if (!result) { //最后一个校验完毕
                        isLegal = result;
                    }
                    if (index == len – 1) { //最后一个校验
                        callback(isLegal);
                    }
                });
            })(validators[i], index)
        }
    }
}
validatorManager.addPattern = function (pattern) {
    if (!pattern.name) {
        return;
    }
    PATTERN[pattern.name] = pattern;
}
validatorManager.addPattern({
    name: “notEmpty”,
    msg: “错误时候的提示”,
    callback: function (value, cb) {
        value = value.trim();
        cb(value != “”);
    }
})

简单的校验组件就这样子完成了。但有些业务场景还是不符合的。
1、一个元素多个校验规则(现在校验的时候 只要一个规则校验完就通知invalid or valid),这个问题其实就相当于ajax多个回调的问题,理所当然我们会想到promise,但我们这边不需要用到promise那么复杂,自己写一个事件队列来处理就OK。
2、有些元素最开始校验,当触发某种状态的时候又不校验(动态校验),管理器里面增加add 和remove 方法

完整代码如下:
javascript 代码

var EventListener = function (obj, type, handle) {
    try { // Chrome、FireFox、Opera、Safari、IE9.0及其以上版本
        obj.addEventListener(type, handle, false);
    } catch (e) {
        try { // IE8.0及其以下版本
            obj.attachEvent(‘on’ + type, handle);
        } catch (e) { // 早期浏览器
            obj[‘on’ + type] = handle;
        }
    }
}
var PATTERN = []; //存放校验规则
var extend = function (child, parent, isOver) { //扩展对象
    if (arguments.length < 2) {
        return child;
    }
    for (var i in parent) {
        if (Object.prototype.toString.call(parent[i]) === “[object Object]”) {
            if (!child[i]) {
                child[i] = {};
            }
            extend(child[i], parent[i], isOver);
        }
        if ((child[i] && isOver) || !child[i]) {
            child[i] = parent[i]
        }
    }
    return child;
}
var noop = function () {}
var asyncQueue = function (callback) {
    this.queue = [];
    this.callback = callback || noop;
    this.isRunning = false;
}
asyncQueue.prototype = {
    add: function (fn) {
        this.queue.push(fn);
    },
    run: function () {
        var me = this;
        if (this.isRunning) {
            return;
        }
        this.isRunning = true;
        var len = this.queue.length;
        var callbackLen = len;
        for (var i = 0; i < len; i++) {
            var queue = this.queue[i];
            queue(function () {
                callbackLen–;
                if (callbackLen == 0) {
                    me.done();
                }
            })
        }
    },
    done: function () {
        this.isRunning = false;
        this.callback();
    }
}
var validator = function (opt) {
    this.opts = extend({
        el: null,
        events: []
    }, opt, true);
    this.el = this.opts.el;
    if (!this.el) {
        throw new Error(“校验规则需要有元素哦”);
    }
    this.__status = false;
    var pattern = this.el.getAttribute(“data-jvalidator”) || “”;
    this.pattern = pattern.replace(/\s+/g, ”).split(“&”);
    this.addEvent();
}
validator.prototype = {
    addEvent: function () {
        var events = this.opts.events || [];
        var el = this.el;
        var me = this;
        for (var i = events.length – 1; i > -1; i–) {
            EventListener(el, events[i], function (e) {
                //Todo 判断是否校验通过
                me.check();
            })
        }
    },
    check: function (callback) {
        var me = this;
        var value = this.el.value;
        var pattern = this.pattern;
        var isLegal = true;
        var unLegalPattern = {};
        //新建队列,并提前写好回调函数
        var asyncQueueInstance = new asyncQueue(function () {
            var arr = [];
            for (var i in unLegalPattern) {
                arr.push(unLegalPattern[i]);
            }
            me.opts.on[isLegal ? “valid” : “invalid”].call(me.el, arr);
            callback && callback(isLegal);
        });
        //给队列添加处理函数
        for (var i = 0, len = pattern.length; i < len; i++) {
            var ruleName = pattern[i];
            var realRule = PATTERN[ruleName];
            if (!realRule) {
                console.error(“不存在校验规则:” + pattern[i] + “,请确认后提交”);
            } else {
                asyncQueueInstance.add(function (next) {
                    realRule.callback.call(this.el, value, function (result) {
                        if (!result) {
                            isLegal = result;
                            unLegalPattern[realRule.name] = realRule;
                        }
                        next();
                    });
                });
            }
        }
        //函数添加完毕之后要执行事件队列
        asyncQueueInstance.run();
    }
}
var validatorManager = function (formEl, opts) {
    this.opts = extend({
        events: [“keyup”, “blur”],
        on: {
            invalid: noop,
            valid: noop
        }
    }, opts || {}, true)
    this.form = formEl;
    this.validators = []; //存放所有的子校验
    this.init();
}
validatorManager.prototype = {
    init: function () {
        var $el = this.form.querySelectorAll(“[data-jvalidator]”);
        var len = $el.length;
        if (len) {
            for (var i = 0; i < len; i++) {
                this.validators.push(new validator(extend({
                    el: $el[i]
                }, this.opts)));
            }
        }
    },
    /**
     * 校验整个表单全部时候填写正确
     * @param {Function} callback 执行完校验之后回调函数
     * @return {[type]} [description]
     */
    validateAll: function (callback) {
        var isLegal = true;
        var validators = this.validators;
        var len = validators.length;
        //新建队列,并提前写好回调函数
        var asyncQueueInstance = new asyncQueue(function () {
            callback && callback(isLegal);
        });
        for (var i = 0; i < len; i++) {
            (function (validator) {
                asyncQueueInstance.add(function (next) {
                    validator.check(function (result) {
                        if (!result) { //最后一个校验完毕
                            isLegal = result;
                        }
                        next();
                    });
                });
            })(validators[i]);
        }
        asyncQueueInstance.run();
    },
    //动态删除其中的校验规则,暂不实现
    remove: function () {},
    //动态添加规则,暂时不实现了
    add: function () {}
}
validatorManager.addPattern = function (pattern) {
    if (!pattern.name) {
        return;
    }
    PATTERN[pattern.name] = pattern;
}

html 代码

<!DOCTYPE html>
<html lang=”en”>
<head>
    <meta charset=”UTF-8″>
    <title>前端开发专业技能怎么写</title>
</head>
<body>
    <form action=”” id=”form”>
        <input type=”text” data-jvalidator=”notEmpty & max10″>
        <span id=”tips”></span>
    </form>
    <button id=”submit” onclick=”check()”>提交订单</button>
    <script type=”text/javascript” src=”validator.js”></script>
    <script type=”text/javascript”>
        var tipsEl = document.getElementById(“tips”);
        var validatorGroup = new validatorManager(document.getElementById(“form”), {
            on: {
                valid: function (pattern) {
                    tipsEl.style.color = “#0f0;”
                    tips.innerHTML = “”;
                },
                invalid: function (pattern) {
                    tipsEl.style.color = “#f00;”
                    tips.innerHTML = pattern[0].msg;
                }
            }
        });
        validatorManager.addPattern({
            name: “notEmpty”,
            msg: “错误时候的提示”,
            callback: function (value, cb) {
                value = value.trim();
                cb(value != “”);
            }
        })
        validatorManager.addPattern({
            name: “max10”,
            msg: “最大不能超过10个字符”,
            callback: function (value, cb) {
                value = value.trim();
                cb(value.length <= 10);
            }
        })
        function check() {
            validatorGroup.validateAll(function (result) {
                alert(result);
            })
        }
    </script>
</body>
</html>
优秀前端开发技能|web前端开发个人技能|前端开发必会的技能
» 本文来自:前端开发者 » 《前端开发js验证插件》
» 本文链接地址:https://www.rokub.com/4000.html
» 您也可以订阅本站:https://www.rokub.com
赞(0)
64K

评论 抢沙发

评论前必须登录!