JS组件化验证检测

页面导航:首页 > 网络编程 > JavaScript > JS组件化验证检测

JS组件化验证检测

来源: 作者: 时间:2016-02-02 09:59 【

作者:Jiang, Jilin在web开发过程中,我们时常会遇到输入检测的情况。如果只是简单的输入验证检测,例如邮箱、电话等。我们可以简单的使用ifelse if来依次判断。但是如果这些判断存在

作者:Jiang, Jilin

 

 

在web开发过程中,我们时常会遇到输入检测的情况。如果只是简单的输入验证检测,例如邮箱、电话等。我们可以简单的使用if…else if…来依次判断。但是如果这些判断存在延迟检测(例如ajax验证),再使用if…else if…已经无法满足需求了。

但是好在,利用jQuery的deffer方法。通过done(func)嵌套,可以实现序列化的检测:


\

 

 

$deferred.done(function() {

// Condition

$deferred.done(function() {

// Condition

$deferred.done(function() {

// Condition

$deferred.done(function() {

// Condition

$deferred.done(function() {

// Condition

// do something

});

});

});

});

});


 

通过嵌套依次进行检测

 

 

通常而言,通过这种嵌套,可以实现大多数的检测判断。但是如果我们考虑如下的检测顺序:

\

 

 

在这种多分支的情况下,使用deffer如下:

 

var _once = true;

function finalCheck() {

if(!_once) return;

_once = false;

 

$deferred.done(function() {

// Condition

// do something

});

}

 

$deferred.done(function() {

// Condition

$deferred.done(function() {

// Condition

$deferred.done(function() {

// Condition

finalCheck();

});

$deferred.done(function() {

// Condition

$deferred.done(function() {

// Condition

finalCheck();

});

});

});

});


 

 

 

可以发现随着分支增多,代码结构会变得越来越复杂。随着时间推移,如果需求变更。需要在判断中增加、删除甚至添加一个分支的时候。你会发现,这种结构很难维护。


那么如何通过封装来将此结构保持最好的维护性呢?我们可以通过将一个个检测条件打包,变成一个个。通过组合组件顺序,便可组织出我们需要的检测结构。

第一种结构设计:

new Condition(function(result) {

// Condition

result.success();

}).next(function(result) {

// Condition

result.success();

}).next(function(result) {

// Condition

result.success();

}).next(function(result) {

// Condition

result.success();

}).next(function(result) {

// Condition

result.success();

}). success(function() {

// do something

}).start();

第二种结构设计:

var seq1 = new Condition(function(result) {

// Condition

result.success();

}).next(function(result) {

// Condition

result.success();

});

 

var seq2_1 = new Condition(function(result) {

// Condition

result.success();

});

var seq2_2 = new Condition(function(result) {

// Condition

result.success()

}).next(function(result) {

// Condition

result.success();

});

 

seq1

.nextOr(seq2_1, seq2_2)

.next(function(result) {

// Condition

result.success();

}). success(function() {

// do something

}).start();


 

\

 

 

接下来,我们开始构建我们的组件容器:

var Condition = function(func) {

this.func = func;

this.root = null;

this.successFunc = null;

return this;

};

 

其中,通过调用next方法,可以添加一个新的检测条件,并返回一个新的组件:

Condition.prototype.next = function(func) {

var _next = new Condition(func);

_next.root = this.root || this;

this._next = _next;

return _next;

};

 

添加success方法用于存储检测成功的回调函数:

Condition.prototype.success = function(func) {

this.successFunc = func;

return this;

};

 

接着,就是添加start事件。当其被调用时,开始整个检测序列:

Condition.prototype._doAction = function() {

var _this = this;

_this.func({

success: function() {

// 如果该组件有success回调,则调用

if(_this.successFunc) {

_this.successFunc();

}

// 如果有后续组件则继续调用

if(_this._next) {

_this._next._doAction();

}

}

});

};

 

Condition.prototype.start = function() {

(this.root || this)._doAction();

};

 

测试如下:

new Condition(function(result) {

console.log(Condition 1);

result.success();

}).success(function() {

console.log(Success 1);

}).next(function(result) {

console.log(Condition 2);

result.success();

}).success(function() {

console.log(Success 2);

}).start();

 

// Condition 1

// Success 1

// Condition 2

// Success 2

 

有时候,我们会需要支持多个success事件,所以可以对success方法进行扩充:

var Condition = function(func) {

this.func = func;

this.root = null;

this.successFunc = [];

return this;

};

Condition.prototype.success = function(func) {

this.successFunc.push(func);

return this;

};

// 如果该组件有success回调,则调用

for(var i = 0 ; i < _this.successFunc.length ; i += 1) {

_this.successFunc[i]();

}

 

 

然后考虑or分支结构,我们使用一个数组保存Condition列表。当执行到包含列表的组件时,遍历执行:

Condition.prototype.nextOr = function() {

var _next = new Condition(function(result) {

result.success();

});

_next.root = this.root || this;

this._next = _next;

 

this._nextList = arguments;

for(var i = 0 ; i < arguments.length ; i += 1) {

arguments[i].success(function() {

_next._doAction();

});

}

return _next;

};

 

同时,我们需要改写_doAction方法,使其支持多个Condition运行:

Condition.prototype._doAction = function() {

var _this = this;

_this.func({

success: function() {

// 如果该组件有success回调,则调用

if(_this.successFunc) {

_this.successFunc();

}

// 如果有后续组件则继续调用

if(_this._next) {

if(_this._nextList) {

for(var i = 0 ; i < _this._nextList.length ; i += 1) {

_this._nextList[i].start ();

}

} else {

_this._next._doAction();

}

}

}

});

};

 

测试如下:

var s1 = new Condition(function(result) {

console.log(Condition 1.1);

result.success();

}).next(function(result) {

console.log(Condition 1.2);

result.success();

});

 

var s2_1 = new Condition(function(result) {

console.log(Condition 2-1);

result.success();

});

var s2_2 = new Condition(function(result) {

console.log(Condition 2-2.1);

result.success();

}).next(function(result) {

console.log(Condition 2-2.2);

result.success();

});

s1.nextOr(s2_1, s2_2).success(function() {

console.log(Condition 3);

}).start();

 

// Condition 1.1

// Condition 1.2

// Condition 2-1

// Condition 3

// Condition 2-2.1

// Condition 2-2.2

// Condition 3

 

我们发现通过两个分支走后,都调用了Condition3,这是我们不希望看到的。我们接下去要实现组件的once:

Condition.prototype.nextOr = function() {

var _once = true;

var _next = new Condition(function(result) {

result.success();

});

_next.root = this.root || this;

this._next = _next;

 

this._nextList = arguments;

for(var i = 0 ; i < arguments.length ; i += 1) {

arguments[i].success(function() {

if(!_once) return;

_once = false;

 

_next._doAction();

});

}

return _next;

};

 

测试如下:

// Condition 1.1

// Condition 1.2

// Condition 2-1

// Condition 3

// Condition 2-2.1

// Condition 2-2.2

 

小贴士:在Condition中使用once和原来的结构中使用once区别是什么?

将分支管理逻辑从代码中剥离可以减少代码复杂度,从而提升代码的可读性和维护性。

 

大致功能已经完成,但是仍然不满意。因为第一个分支已经成功的情况下,第二个分支还是走了一边。在不产生效果的情况下,该分支其实可以跳过。对doAction进行扩展:

Condition.prototype._doAction = function() {

var _succeed = false;

var _this = this;

var i;

 

_this.func({

success: function() {

// 如果该组件有success回调,则调用

for(i = 0 ; i < _this.successFunc.length ; i += 1) {

_this.successFunc[i]();

}

// 如果有后续组件则继续调用

if(_this._next) {

if(_this._nextList) {

for(i = 0 ; i < _this._nextList.length ; i += 1) {

if(_succeed) break;

 

_this._nextList[i].success(function() {

_succeed = true;

}).start();

}

} else {

_this._next._doAction();

}

}

}

});

};

 

测试如下:

// Condition 1.1

// Condition 1.2

// Condition 2-1

// Condition 3

 

还没有结束,如果分支中存在延迟操作,例如ajax请求等。仍然会走遍所有分支:

var s1 = new Condition(function(result) {

console.log(Condition 1.1);

result.success();

}).next(function(result) {

console.log(Condition 1.2);

result.success();

});

 

var s2_1 = new Condition(function(result) {

console.log(Condition 2-1);

setTimeout(function() {

result.success();

}, 100);

});

var s2_2 = new Condition(function(result) {

console.log(Condition 2-2.1);

setTimeout(function() {

result.success();

}, 100);

}).next(function(result) {

console.log(Condition 2-2.2);

setTimeout(function() {

result.success();

}, 100);

});

s1.nextOr(s2_1, s2_2).success(function() {

console.log(Condition 3);

}).start();

 

// Condition 1.1

// Condition 1.2

// Condition 2-1

// Condition 2-2.1

// Condition 3

// Condition 2-2.2

 

给每个分支添加一个标示符,当标示符为false时,停止该分支还未运行的所有检测:

var Condition = function(func) {

this.func = func;

this.root = null;

this.successFunc = [];

this._stop = false;

return this;

};

Condition.prototype._doAction = function() {

var _succeed = false;

var _this = this;

var i;

if((this.root || this)._stop) return;

};

Condition.prototype.start = function() {

(this.root || this)._stop = false;

(this.root || this)._doAction();

};

Condition.prototype.nextOr = function() {

var _once = true;

var _this = this;

var i;

 

var _next = new Condition(function(result) {

result.success();

});

_next.root = _this.root || _this;

_this._next = _next;

 

_this._nextList = arguments;

function doSuccess() {

for(i = 0 ; i < _this._nextList.length ; i += 1) {

var _root = _this._nextList[i];

_root = _root.root || _root;

_root._stop = true;

}

 

if(!_once) return;

_once = false;

 

_next._doAction();

}

for(i = 0 ; i < arguments.length ; i += 1) {

arguments[i].success(function() {

doSuccess();

});

}

return _next;

};

 

测试如下:

// Condition 1.1

// Condition 1.2

// Condition 2-1

// Condition 2-2.1

// Condition 3

 

好了,一个简易版的组件就完成了,通过这种组件化方式可以可方便的在中间插入、删除一个新的条件检测,也可以很容易创建一个分支检测。此处仅作抛砖引玉,考虑更复杂的情况,还有fail、always等事件处理。就让各位自己尝试着完成吧。

 

 


Tags:

相关文章

    文章评论

    最 近 更 新
    热 点 排 行
    Js与CSS工具
    代码转换工具
    
    <