【问题标题】:How to do contextual pre-loader for ajax properly?如何正确地为 ajax 做上下文预加载器?
【发布时间】:2014-06-20 14:43:52
【问题描述】:

我的计划是在不修改代码的情况下对所有 ajax 调用使用上下文预加载器。按照惯例,我的 ajax 调用是这样的。

// do some pre-loader for example spinning wheel
$('#submitBnt').on('click', function () {
    $.get('/echo/json', function (data) {
        // after everything is done do some cleanup for the UI
    });
});

但是,我想在全局级别构建预加载器,这样任何 ajax 调用都会将旋转轮附加到容器并在一切完成后取消它。

到目前为止,这是我的代码,当然这不起作用。

var s_ajaxListener = new Object();
var target;
s_ajaxListener.tempOpen = XMLHttpRequest.prototype.open;
s_ajaxListener.tempSend = XMLHttpRequest.prototype.send;
s_ajaxListener.callback = function () {
    console.log('last');
    $('.ajaxContainer').removeClass('pre-loader');
}

XMLHttpRequest.prototype.open = function (a, b) {
    console.log('first');
    $(document).on('click', function (e) {
        target = e.target;
        $(target).closest('.ajaxContainer').addClass('pre-loader');
    });
    if (!a) var a = '';
    if (!b) var b = '';
    s_ajaxListener.tempOpen.apply(this, arguments);
    s_ajaxListener.method = a;
    s_ajaxListener.url = b;
    if (a.toLowerCase() == 'get') {
        s_ajaxListener.data = b.split('?');
        s_ajaxListener.data = s_ajaxListener.data[1];
    }
}

XMLHttpRequest.prototype.send = function (a, b) {
    if (!a) var a = '';
    if (!b) var b = '';
    s_ajaxListener.tempSend.apply(this, arguments);
    if (s_ajaxListener.method.toLowerCase() == 'post') s_ajaxListener.data = a;
    s_ajaxListener.callback();
}


$('#submitBnt').on('click', function () {
    $.get('/echo/json', function (data) {
        console.log(data);
    });
});

我的问题是 1. 为什么它不起作用。 2. 添加 $(document).on('click') 是个好主意,因为我认为它会将点击事件添加到全局事件中,这对于移动网站来说是否太多了?

这是我的小提琴 http://jsfiddle.net/noppanit/xke87/2/

谢谢。

【问题讨论】:

    标签: javascript ajax html zepto


    【解决方案1】:

    首先,您应该小心扩展原生对象原型。

    其次,如果您使用的是 jQuery,那么使用 $.ajaxStart() 和 $.ajaxComplete() 为所有 ajax 调用设置开始和结束操作很容易实现您想要做的事情。你可以在这里阅读:https://api.jquery.com/ajaxStart/,在这里:https://api.jquery.com/ajaxComplete/。

    一个基本的实现:

    $( document )
    .ajaxStart(function() {
        $( e.target )closest('.ajaxContainer').addClass('pre-loader');
    })
    .ajaxComplete(function() {
        $( e.target )closest('.ajaxContainer').removeClass('pre-loader');
    });
    

    这适用于文档中触发 ajax 请求的任何点击。

    Zepto 在 ajax 请求和 ajax 请求的生命周期中触发一些事件,因此您可以使用 Zepto 的 ajaxBeforeSend 和 ajaxComplete 执行与 jQuery 中相同的操作:

    $(document)
    .on('ajaxBeforeSend', function(e, xhr, options) {
        // show your loader
    })
    .on('ajaxComplete', function(e, xhr, options) {
        // hide your loader
    });
    

    根据他们的文档,这些事件是在文档对象上触发的,因此您可以在全局范围内监听它们,并且它们将为您发出的每个 ajax 请求运行。 ajaxBeforeSend 让您可以访问您的请求对象、触发 ajax 请求的事件以及传递给请求的选项。所以你可以用它做很多事情。你可以在这里阅读更多内容:http://zeptojs.com/#$.ajax

    【讨论】:

    • 感谢您的回复,在我的项目中我使用的是zepto,我认为zepto没有那个方法。因为,这是一个移动网站,所以我将 js 保持在最低限度。如果你有 zepto 或纯 javascript 的解决方案,那就太棒了。
    • 我更新了我的答案以涵盖 Zepto。希望对您有所帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-04-04
    • 1970-01-01
    • 2020-03-13
    • 2015-07-18
    • 2020-10-04
    • 2023-02-21
    • 2013-08-09
    相关资源
    最近更新 更多