如何在jQuery中显示加载动画?

442

Prototype 中,我可以使用以下代码显示“加载中...”的图片:

var myAjax = new Ajax.Request( url, {method: 'get', parameters: pars, 
onLoading: showLoad, onComplete: showResponse} );

function showLoad () {
    ...
}
在jQuery中,我可以使用以下代码将服务器页面加载到元素中:
$('#message').load('index.php?pg=ajaxFlashcard');

但我该如何像在Prototype中一样,为这个命令添加一个loading spinner呢?

25个回答

830

有几种方法。我偏爱的方法是将一个函数附加到元素本身的ajaxStart/Stop事件上。

$('#loadingDiv')
    .hide()  // Hide it initially
    .ajaxStart(function() {
        $(this).show();
    })
    .ajaxStop(function() {
        $(this).hide();
    })
;

无论何时您进行任何 Ajax 调用,ajaxStart/Stop 函数都会触发。

更新:从 jQuery 1.8 版本开始,文档说明 .ajaxStart/Stop 应该只附加到 document。因此,将上面的代码片段转换为:

var $loading = $('#loadingDiv').hide();
$(document)
  .ajaxStart(function () {
    $loading.show();
  })
  .ajaxStop(function () {
    $loading.hide();
  });

51
这可能对于一个简单的DIV加载来说太过全局化了。 - montrealist
379
太过笼统?你想要多少种不同的“请稍等”信息? - nickf
25
很遗憾,如果你不想只显示一个模态加载窗口,而是想在等待ajax内容加载的元素附近显示它,那么你无法控制加载div的位置。 - glaz666
10
ajaxStart和ajaxStop是jQuery事件,因此您可以给它们命名空间:https://dev59.com/6HM_5IYBdhLWcg3w3nRs#1212728 http://docs.jquery.com/Namespaced_Events - David Xia
10
如果使用jQuery >= 1.9版本,请将ajaxStart和ajaxStop事件附加到$(document)对象。http://jquery.com/upgrade-guide/1.9/#ajax-events-should-be-attached-to-document - Dom M.
显示剩余3条评论

234

对于 jQuery,我使用:

jQuery.ajaxSetup({
  beforeSend: function() {
     $('#loader').show();
  },
  complete: function(){
     $('#loader').hide();
  },
  success: function() {}
});

13
我的工作适用,HTML应该类似于:<div id='loader'><img src="spinner.gif"/></div> - yigal
7
对我来说,这种方式最清晰明了。我将 beforeSend: 和 complete: 放在 $ajax({... 语句中,而不是使用 ajaxSetup。 - kenswdev
5
不知道价值如何,但是jQuery在其文档中提到不建议使用_.ajaxSetup()_。链接 - pec
请注意,beforeSend在每次调用之前都会被调用,而ajaxStart仅在第一个ajax方法被调用时触发。同样地,ajaxStop在最后一个ajax调用完成时被调用。如果您有多个并发请求,则此答案中的代码片段将无法正常工作。 - nickf
如果 AJAX 调用超时(Mac 上的 Firefox 28),对我无效。 - Sergey Orshanskiy
ajaxSetup就像是Ajax请求的通用设置。 - mercury

58
您可以直接使用jQuery的.ajax函数,并使用其选项beforeSend,定义一个函数,在其中显示类似于加载器div的内容,然后在成功的选项中隐藏该加载器div。
jQuery.ajax({
    type: "POST",
    url: 'YOU_URL_TO_WHICH_DATA_SEND',
    data:'YOUR_DATA_TO_SEND',
    beforeSend: function() {
        $("#loaderDiv").show();
    },
    success: function(data) {
        $("#loaderDiv").hide();
    }
});

您可以使用任何旋转gif图像。这里有一个网站,根据您的颜色方案提供了一个很棒的AJAX Loader生成器:http://ajaxload.info/


20
根据jQuery Ajax Events的说法,如果出现错误,则不会调用“success”,但是“即使是同步请求,您也将始终收到complete回调”。 - Lee Goddard

28

如果你正在使用 $.ajax(),你可以像这样使用:

$.ajax({
  url: "destination url",
  success: sdialog,
  error: edialog,
  // shows the loader element before sending.
  beforeSend: function() {
    $("#imgSpinner1").show();
  },
  // hides the loader after completion of request, whether successfull or failor.             
  complete: function() {
    $("#imgSpinner1").hide();
  },
  type: 'POST',
  dataType: 'json'
});

虽然设置名为“beforeSend”,但是自jQuery 1.5以来,“beforeSend”将被调用,无论请求类型如何。例如,如果type: 'GET',则会调用.show()函数。


25
你可以在 AJAX 调用之前将动画图像插入到 DOM 中,并进行内联函数以删除它...

你可以在 AJAX 调用之前将动画图像插入到 DOM 中,并进行内联函数以删除它...

$("#myDiv").html('<img src="images/spinner.gif" alt="Wait" />');
$('#message').load('index.php?pg=ajaxFlashcard', null, function() {
  $("#myDiv").html('');
});

这将确保您的动画在后续请求中从相同的帧开始(如果有必要的话)。请注意,旧版本的IE可能会对动画产生困难。

祝好运!


13
顶级提示:在具有"display: none"属性的div中预加载spinner.gif。否则,由于spinner仍在下载中,您可能会遇到稍有延迟的旋转效果。 - uriDium
不错的提示,比使用别人的插件简单得多。 - Gordon Thompson
不错!但是亲爱的,我还想在页面已经加载完成后再显示旋转图标2秒钟。 - Both FM
6
因为人们喜欢等待事情发生...? - Josh Stodola

21

你可能会有时间上的问题,不是吗? - Tim Büthe
2
@UltimateBrent,我认为你理解错了。为什么showLoad()不是回调函数?JavaScript将异步加载内容。如果我没记错的话,即使在内容加载之前,showLoad()也可以正常工作。 - Jaseem
2
@Jaseem 我也使用类似的方法,它实际上依赖于异步调用。我会在ajax调用之前放置showLoad,但整个重点是显示旋转图标,让JS开始调用,在AJAX完成后的回调函数中停止旋转图标。 - Joel Peltonen

11

10
一个插件来完成这个简单的任务吗?这真的不是一个好的解决方案,对吧?谁想要在页面上加载100个脚本? - Jaseem
2
同意。如果您想要更好的性能,请压缩和连接。 - Nathan Bubna
9
分离和模块化、重复利用代码是保持你的工作可维护性并让他人也能够维护的途径。你的用户使用的网络连接质量差到无法加载插件和代码的概率有多大? - Lee Goddard
@NathanBubna 这个链接已经失效了。 - SpringLearner
你的用户连接如此差,以至于他们的客户端无法加载插件和你的代码的机会有多大?我认为相当高。 - andrew oxenburgh

9

变量:我在主页面的左上角有一个id为“logo”的图标;当ajax正在工作时,一个带透明度的旋转gif会覆盖在上面。

jQuery.ajaxSetup({
  beforeSend: function() {
     $('#logo').css('background', 'url(images/ajax-loader.gif) no-repeat')
  },
  complete: function(){
     $('#logo').css('background', 'none')
  },
  success: function() {}
});

9
我也希望对这个问题做出贡献。我在jQuery中寻找类似的东西,最终使用了以下内容。
我的加载动画来自http://ajaxload.info/。我的解决方案基于http://christierney.com/2011/03/23/global-ajax-loading-spinners/的一个简单答案。
基本上,你的HTML标记和CSS应该像下面这样:
<style>
     #ajaxSpinnerImage {
          display: none;
     }
</style>

<div id="ajaxSpinnerContainer">
     <img src="~/Content/ajax-loader.gif" id="ajaxSpinnerImage" title="working..." />
</div>

然后,你编写jQuery的代码将类似于这样:
<script>
     $(document).ready(function () {
          $(document)
          .ajaxStart(function () {
               $("#ajaxSpinnerImage").show();
          })
          .ajaxStop(function () {
               $("#ajaxSpinnerImage").hide();
          });

          var owmAPI = "http://api.openweathermap.org/data/2.5/weather?q=London,uk&APPID=YourAppID";
          $.getJSON(owmAPI)
          .done(function (data) {
               alert(data.coord.lon);
          })
          .fail(function () {
               alert('error');
          });
     });
</script>

这很简单 :)

9

我对原回答进行了两个更改。

  1. 从jQuery 1.8开始,ajaxStart和ajaxStop应该只附加到document。这使得仅筛选一些ajax请求变得更加困难。所以...
  2. 切换到ajaxSendajaxComplete可以在显示旋转器之前检查当前的ajax请求。

这是经过这些更改后的代码:

$(document)
    .hide()  // hide it initially
    .ajaxSend(function(event, jqxhr, settings) {
        if (settings.url !== "ajax/request.php") return;
        $(".spinner").show();
    })
    .ajaxComplete(function(event, jqxhr, settings) {
        if (settings.url !== "ajax/request.php") return;
        $(".spinner").hide();
    })

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接