可能大家都听说过或者使用过javascript中的命令模式,它其中一个应用就是封装其他的对象或者类,并带有execute或者run、undo或者redo等等方法来执行代码,并且提供了回退操作,把每一步的操作记录在队列里,之后可以一步一步来回退操作。这个应用在很多方面都可能涉及到的,尤其是一些ajax应用方面。
下面我将要介绍的后退操作实现方式中,并没有使用命令模式,而是提供了几种实现的思路,其他形式的封装都是允许而且可行的。
第一种:使用计步器step。这种方式的实现方式是通过一个正向的计步器,当你正向操作了多少次,计步器都会自动增加步数,之后在回退的倒退一步一步回退回来。比如下面的这种情况:
//上面的实现方式的适用范围很小,在现实的需求中也比较少这样的功能
var Move = {
step: 0, //计步器
run: function(elem){
//每正向执行一次,计步器就加1
this.step++;
elem.style.left = (parseInt(elem.style.left) + 5) + "px";
},
undo: function(elem){
//根据计步器来一步一步回退
if (this.step-- > 0) {
elem.style.left = (parseInt(elem.style.left) - 5) + "px";
}
else {
this.step = 0;
}
}
}
第二种方式:储存每一步对应的后退函数。它的实现方式是把跟正向操作的函数相反的操作的函数储存进数组,之后在回退的时候,就可以从数组中获得每一步的回退函数并执行。如下代码所示:
//下面的代码中有一个缺点是参数的传递问题
var Move = {
step: [], //储存回退函数
run: function(elem){
elem.style.left = (parseInt(elem.style.left) + 5) + "px";
this.step.push(this._undo);//储存每一步对应的后退函数到数组里
},
_undo: function(elem){
elem.style.left = (parseInt(elem.style.left) - 5) + "px";
},
undo: function(elem){
var t = this.step.pop();
if (t) {
t(elem);//执行每一步的后退函数
}
}
}
这种方式还有一种变体的方式:储存每一步的参数。下面展示一个Ajax在这方面的一个应用:
var XHR = function(){
var xhr = null;
if (window.XMLHttpRequest) {
xhr = new XMLHttpRequest();
}
else {
try { xhr = new ActiveXObject("Msxml2.XMLHTTP"); }
catch (e) { xhr = new ActiveXObject("Microsoft.XMLHTTP"); }
}
return xhr;
}
var ajaxGet = function(url, handle){
var xhr = XHR();
xhr.open("GET", url, true);
xhr.onreadystatechange = function(){
if (xhr.readyState === 4 && (xhr.status === 200 || xhr.status === 304)) {
handle(xhr);
}
}
xhr.send(null);
}
////////////////// 关键代码 ////////////////////////////////
var backToPrevious = {
step: [], //用于储存每一步的参数
previous: null, //储存前一步的参数
run: function(url, handle){
this.step.push(this.previous); //储存每一步的参数
this.previous = {"url": url,"handle": handle};
ajaxGet(url, handle);
},
undo: function(){
var item = this.step.pop();
if (item) {
ajaxGet(item.url, item.handle);
}
}
}
当然在上面的示例中可以结合上面的储存函数的方式,将函数和参数都储存起来,之后可以一步步回退操作。《测试页面》