几种后退操作实现方式

可能大家都听说过或者使用过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);
        }
    }
}

当然在上面的示例中可以结合上面的储存函数的方式,将函数和参数都储存起来,之后可以一步步回退操作。《测试页面

你的手印呢?