利用jQuery全局事件ajaxStart为特定请求实现提示效果

情景

如何在特定的请求上实现"ajaxStart"的效果?

首先,重写Ajax方法的代价太高,仍然可以利用jQuery自身的Ajax Events

Ajax触发的全局事件会像一个标准事件一样传播到所有DOM节点上。层级:jQuery Events > Ajax Events > 自定义Ajax事件。

实现


Wo = window.Wo || {};
Wo.ajax = {
    spinner    : $([])
    ,init    : function() {
        var $spinner = this.spinner = $('#ajax-loading');
        var show = function(e) {
            if(e.namespace === 'Wo') $spinner.show();
        };
        var hide = function(e) {
            $spinner.hide();
        };
        $spinner.bind({
            'ajaxStart.Wo'      : show
            ,'ajaxStop.Wo'      : hide
            ,'ajaxError.Wo'     : hide
        });

        this.adapt(['getJSON','get','post','ajax']);
    }
    // 预备发送请求
    ,_prepare : function() {
        this.spinner.trigger('ajaxStart.Wo');
    }
    // 接口批量变更
    ,adapt    : function(fns) {
        var self = this;
        $.each(fns,function(i,fn) {
            Wo[fn] = function() {
                self._prepare();
                $[fn].apply(this,arguments);
            }
        });        
    }
};

有两种方法可以判断出触发的事件是否为特定的事件:

  • 确定的命名空间。
  • 在触发时传递额外的参数给事件处理程序。

这里用事件的命名空间来进行触发来源的判断。adapt方法相当于适配器的应用,用一套改善的接口替代了另一套接口。

如果要增加load方法,稍微麻烦一点,因为有可能是ajax方法或者元素的onload事件。

要添加一个代理方法,并进行类型判断:


        var _load = $.fn.load;
        $.fn.load = function() {
                $.type(arguments[0]) === 'string' && self._prepare();
                _load.apply(this,arguments);
                return this;
        };

使用

所有方法参数仍与原先一致:


Wo.post(url, [data,] callback)

PS: jQuery 1.5 之后有更好的做法,参见 jQuery ajax 路由和过滤器