jQuery AJAX"撤消助手"

Tom*_*ski 5 javascript jquery

基于AJAX的UI中的常见模式是,当用户执行操作时,它会立即反映在UI中,但在到达AJAX响应确认一切正常之前标记为未完成.这就是在Google日历中添加活动的方式.当出现错误时,将恢复临时UI更改.

现在,手动进行这样的回归并不是太有创意,所以我怀疑jQuery中有一些"撤消助手",它允许保留UI元素的状态,然后恢复它 - 一种属性堆栈或类似的东西.这甚至不必与AJAX有任何关系.

有什么相似的吗?

Mat*_*att 7

在这种情况下,我总是发现状态机是可行的方法.设计您的页面/ JavaScript,以便在任何时间点您都可以指定一组输入,并且您将始终在整个页面上获得相同的输出.这种方法的好处是你不知道你如何到达你的程序中的位置,你只需要知道当前状态产生了什么数据.

对于您的情况,您可以创建一个描述您的州的基本对象:

var state = { user: 'Tomasz', ajaxSent: false, otherState: 123 };

function updateFromState(state){
    // Set all dependent UI visibilities, etc. based on state object
}
Run Code Online (Sandbox Code Playgroud)

然后,在进行任何更改之前,将当前状态推送到阵列,以便在需要时可以恢复:

var stateList = [];
stateList.push({ user: 'Tomasz', ajaxSent: false, otherState: 123 });

// Do something that changes your state
var newState =  {user: 'Tomasz', ajaxSent: true, otherState: 123 };
updateFromState(newState);

// Now, if you need to revert
var previousState = stateList.pop();
updateFromState(previousState);
Run Code Online (Sandbox Code Playgroud)

这种方法的缺点是你实际上并没有"撤消"你可能调用过的任何副作用.例如,如果您在服务器上创建了修改数据的AJAX帖子,则必须了解如何"撤消"该AJAX帖子.这不仅仅是改变页面的本地状态.但是,如果您不需要撤消服务器端效果,但只是能够准确反映页面的正确状态,这可能对您有用.

如果我做这样的事情,我可能会开始使用以下内容:

var StateHelper = function(){
    var stateList = [];
    var callbacks = [];

    this.onChange = function(callback){
        callbacks.push(callback);
    };

    this.set = function(opts){
        stateList.push(opts);
        apply(opts);
    };

    this.undo = function(){
        if(stateList.length <= 1){
            return; // nothing to undo
        }

        // To undo, we go back 2, since top of stack is current
        stateList.pop();
        var last = stateList[stateList.length - 1];
        apply(last);
    };

    var apply = function(opts){
        var length = callbacks.length;
        for(var i = 0; i < length; i++){
            callbacks[i](opts);
        }
    };
};
Run Code Online (Sandbox Code Playgroud)

然后,如果我的页面看起来像这样:

<div id='title' style='text-decoration: underline;'>some title</div>
<div id='state1' class='clickable'>click to set state2 (title = 'second')</div>
<div id='state2' class='clickable'>click to set state3  (title = 'third')</div>
<br/>
<div id='undo' class='clickable'>undo</div>
Run Code Online (Sandbox Code Playgroud)

我可能会像这样使用上面的StateHelper(注意我使用了一点jQuery):

// A function that should be called when state changes
var updateTitle = function(opts){
    // Update the pages title based on state
    console.log('title updating');
    $('#title').text(opts.title);
};

var myState = new StateHelper();
myState.onChange(updateTitle);  // hook the state change event

// some example states
var state2 = { title: 'second' };
var state3 = { title: 'third' };

// Just some click handlers
$(document).ready(function(){
    $('#state1').click(function(){
        myState.set(state2);
    });

    $('#state2').click(function(){
        myState.set(state3);
    });

    $('#undo').click(function(){
        myState.undo();
    });

    // Set initial state
    myState.set({title: 'some title'});
});
Run Code Online (Sandbox Code Playgroud)

有关实例,请参阅:http://jsfiddle.net/belorion/Hywtc/