Làm thế nào để hiển thị tải spinner trong jQuery?


412

Trong Prototype tôi có thể hiển thị hình ảnh "đang tải ..." với mã này:

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

function showLoad () {
    ...
}

Trong jQuery , tôi có thể tải một trang máy chủ vào một phần tử với điều này:

$('#message').load('index.php?pg=ajaxFlashcard');

nhưng làm cách nào để đính kèm một spinner tải vào lệnh này như tôi đã làm trong Prototype?

Câu trả lời:


793

Có một vài cách khác nhau. Cách ưa thích của tôi là gắn một hàm vào các sự kiện ajaxStart / Stop trên chính phần tử đó.

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

Các hàm ajaxStart / Stop sẽ kích hoạt bất cứ khi nào bạn thực hiện bất kỳ cuộc gọi Ajax nào.

Cập nhật : Kể từ jQuery 1.8, các trạng thái tài liệu .ajaxStart/Stopchỉ nên được đính kèm document. Điều này sẽ chuyển đổi đoạn trích trên thành:

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

48
Điều đó có lẽ quá toàn cầu đối với một tải đơn giản vào DIV.
montrealist

363
quá toàn cầu? bạn muốn có bao nhiêu tin nhắn "vui lòng chờ"?
nickf

23
Thật không may, bạn không thể kiểm soát tải định vị div trong trường hợp bạn không muốn chỉ hiển thị cửa sổ tải phương thức, nhưng hiển thị nó gần phần tử đang chờ nội dung ajax được tải trong ...
glaz666

10
ajaxStart và ajaxStop là các sự kiện jQuery để bạn có thể đặt tên cho chúng: stackoverflow.com/questions/1191485/iêu docs.jquery.com/Namespaces_Events
David Xia

10
Nếu sử dụng jQuery> = 1.9, hãy đính kèm các sự kiện ajaxStart và ajaxStop vào $ (tài liệu). jquery.com/upTHER-guide/1.9/
Domenic

213

Đối với jQuery tôi sử dụng

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

13
hoạt động với tôi, html nên có cái gì đó như: <div id = 'loader'> <img src = "spinner.gif" /> </ div>
yigal

7
Điều này là sạch nhất đối với tôi. Thay vì ajaxSetup, tôi đã đặt trướcSend: và hoàn thành: bên trong câu lệnh $ ajax ({...
kenswdev

4
Không biết giá trị của nó là gì, nhưng jQuery đề cập đến trong tài liệu của nó rằng không sử dụng .ajaxSetup () . liên kết
pec

Lưu ý ở đây beforeSendđược gọi trước mỗi cuộc gọi, trong khi chỉ ajaxStartđược kích hoạt khi phương thức ajax đầu tiên được gọi. Tương tự như vậy ajaxStop, nó được gọi khi cuộc gọi ajax cuối cùng kết thúc. Nếu bạn có nhiều yêu cầu đồng thời, đoạn trích trong câu trả lời này sẽ không hoạt động chính xác.
nickf

Không hoạt động với tôi nếu cuộc gọi ajax hết thời gian (Firefox 28 cho Mac).
osa

48

Bạn chỉ có thể sử dụng .ajaxhàm của jQuery và sử dụng tùy chọn của nó beforeSendvà xác định một số hàm trong đó bạn có thể hiển thị một cái gì đó như div của trình tải và trên tùy chọn thành công, bạn có thể ẩn div trình tải đó.

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();
    }
});

Bạn có thể có bất kỳ hình ảnh Quay Gif. Đây là một trang web là một Trình tạo AJAX Loader tuyệt vời theo bảng màu của bạn: http://ajaxload.info/


16
Các successsẽ không được gọi là nếu có một lỗi, nhưng "bạn sẽ luôn nhận được một completecuộc gọi lại, ngay cả đối với yêu cầu đồng bộ", theo jQuery Ajax Sự kiện .
LeeGee

23

Bạn có thể chèn hình ảnh hoạt hình vào DOM ngay trước cuộc gọi AJAX và thực hiện chức năng nội tuyến để xóa nó ...

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

Điều này sẽ đảm bảo hoạt hình của bạn bắt đầu ở cùng một khung cho các yêu cầu tiếp theo (nếu có vấn đề). Lưu ý rằng các phiên bản IE cũ có thể gặp khó khăn với hình ảnh động.

Chúc may mắn!


13
Mẹo hàng đầu: Tải trước spinner.gif trong div với màn hình được đặt thành không. Nếu không, bạn có thể nhận được một chút hiệu ứng spinner bị trì hoãn khi spinner vẫn tải xuống.
uriDium

mẹo hay, đơn giản hơn nhiều so với sử dụng plugin của người khác
Gordon Thompson

Đẹp! nhưng thân yêu, một điều nữa mà tôi muốn hiển thị spinner trong 2 giây ngay cả khi trang đã được tải.
Cả FM

5
@BothFM Bởi vì mọi người thích chờ đợi mọi thứ ...?
Josh Stodola

21
$('#message').load('index.php?pg=ajaxFlashcard', null, showResponse);
showLoad();

function showResponse() {
    hideLoad();
    ...
}

http://docs.jquery.com/Ajax/load#urldatacallback


Bạn có thể có vấn đề thời gian ở đó, phải không?
Tim Büthe

2
@UltimateBrent Tôi nghĩ bạn đã hiểu sai. Tại sao showLoad () không phải là một cuộc gọi lại? JavaScript sẽ tải nội dung không đồng bộ. showLoad () sẽ hoạt động ngay cả trước khi nội dung được tải nếu tôi đúng.
Jaseem

2
@Jaseem Tôi cũng sử dụng một phương thức tương tự và nó thực sự dựa vào các cuộc gọi không đồng bộ. Tôi sẽ đặt showLoad ở đâu đó trước cuộc gọi ajax nhưng toàn bộ vấn đề là hiển thị một công cụ quay vòng, hãy để JS bắt đầu cuộc gọi và tiêu diệt công cụ quay vòng trong cuộc gọi lại sau khi AJAX hoàn thành.
Nenotlep

17

Nếu bạn đang sử dụng, $.ajax()bạn có thể sử dụng một cái gì đó như thế này:

$.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'
    });  

11

Sử dụng plugin tải: http://plugins.jquery.com/project/loading

$.loading.onAjax({img:'loading.gif'});

10
Một plugin cho nhiệm vụ đơn giản này? Đó không thực sự là một giải pháp tốt phải không? Ai muốn tải 100 tập lệnh trên một trang?
Jaseem

2
Đã đồng ý. Nén và nối, nếu bạn muốn hiệu suất tốt hơn.
Nathan Bubna

9
Không đồng ý: tách biệt và mô đun hóa, sử dụng lại mã, nếu bạn muốn có thể duy trì công việc của mình và nhờ người khác làm như vậy. Cơ hội người dùng của bạn có kết nối kém như vậy là khách hàng của họ không thể tải plugin cũng như mã của bạn?
LeeGee

@NathanBubna Liên kết đã chết
SpringLearner

"Cơ hội nào cho người dùng của bạn có kết nối kém như vậy, khách hàng của họ không thể tải plugin cũng như mã của bạn?" Khá tốt tôi muốn nói.
andrew oxenburgh

9

Biến thể: Tôi có một biểu tượng với id = "logo" ở trên cùng bên trái của trang chính; một gif spinner sau đó được phủ lên trên (với độ trong suốt) khi ajax đang hoạt động.

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

9

Tôi đã kết thúc với hai thay đổi để trả lời ban đầu .

  1. Kể từ jQuery 1.8, chỉ nên đính kèm ajaxStart và ajaxStop document. Điều này làm cho việc lọc chỉ một số yêu cầu ajax trở nên khó khăn hơn. Ôi ...
  2. Chuyển sang ajaxSendajaxComplete giúp có thể xen kẽ yêu cầu ajax hiện tại trước khi hiển thị spinner.

Đây là mã sau những thay đổi này:

$(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();
    })

Cách giải quyết tốt đẹp. ajaxCompletedường như bắn sớm khi yêu cầu thử lại, vì vậy tôi đã sử dụng một sự kết hợp của ajaxSendajaxStopvà nó hoạt động tuyệt vời.
Mahn

@SchweizerSchoggi: Có những chủ đề khác trả lời câu hỏi đó, hãy sử dụng tìm kiếm!
Emil Stenström

8

Tôi cũng muốn đóng góp cho câu trả lời này. Tôi đã tìm kiếm một cái gì đó tương tự trong jQuery và đây là thứ mà cuối cùng tôi đã sử dụng.

Tôi đã nhận được spinner tải của mình từ http://ajaxload.info/ . Giải pháp của tôi dựa trên câu trả lời đơn giản này tại http://christierney.com/2011/03/23/global-ajax-loading-spinners/ .

Về cơ bản, đánh dấu HTML và CSS của bạn sẽ như thế này:

<style>
     #ajaxSpinnerImage {
          display: none;
     }
</style>

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

Và sau đó, mã của bạn cho jQuery sẽ trông giống như thế này:

<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>

Nó đơn giản như vậy :)


8

Bạn có thể chỉ cần gán một hình ảnh trình tải cho cùng một thẻ mà sau đó bạn sẽ tải nội dung bằng một cuộc gọi Ajax:

$("#message").html('<span>Loading...</span>');

$('#message').load('index.php?pg=ajaxFlashcard');

Bạn cũng có thể thay thế thẻ span bằng thẻ hình ảnh.


1
Sẽ khó quản lý UI theo cách này. Chúng tôi có thể cần các kiểu hoàn toàn khác nhau cho văn bản "tải" và tin nhắn cuối cùng. Chúng ta có thể sử dụng phương thức gọi lại được đề cập ở trên để xử lý vấn đề này
Jaseem

6

Cũng như đặt mặc định toàn cầu cho các sự kiện ajax, bạn có thể đặt hành vi cho các yếu tố cụ thể. Có lẽ chỉ cần thay đổi lớp học của họ là đủ?

$('#myForm').ajaxSend( function() {
    $(this).addClass('loading');
});
$('#myForm').ajaxComplete( function(){
    $(this).removeClass('loading');
});

Ví dụ CSS, để ẩn #myForm với một công cụ quay vòng:

.loading {
    display: block;
    background: url(spinner.gif) no-repeat center middle;
    width: 124px;
    height: 124px;
    margin: 0 auto;
}
/* Hide all the children of the 'loading' element */
.loading * {
    display: none;  
}

1
Đây phải là câu trả lời được lựa chọn trong quan điểm của tôi. Cảm ơn @LeeGee.
Nam G VU

Câu trả lời thực sự tuyệt vời
Raskolnikov

4

Lưu ý rằng bạn phải sử dụng các cuộc gọi không đồng bộ để các spinners hoạt động (ít nhất đó là nguyên nhân khiến tôi không hiển thị cho đến sau cuộc gọi ajax và sau đó nhanh chóng biến mất khi cuộc gọi kết thúc và gỡ bỏ spinner).

$.ajax({
        url: requestUrl,
        data: data,
        dataType: 'JSON',
        processData: false,
        type: requestMethod,
        async: true,                         <<<<<<------ set async to true
        accepts: 'application/json',
        contentType: 'application/json',
        success: function (restResponse) {
            // something here
        },
        error: function (restResponse) {
            // something here                
        }
    });

4
$('#loading-image').html('<img src="/images/ajax-loader.gif"> Sending...');

        $.ajax({
            url:  uri,
            cache: false,
            success: function(){
                $('#loading-image').html('');           
            },

           error:   function(jqXHR, textStatus, errorThrown) {
            var text =  "Error has occured when submitting the job: "+jqXHR.status+ " Contact IT dept";
           $('#loading-image').html('<span style="color:red">'+text +'  </span>');

            }
        });

Cách ngắn nhất là chèn thẻ hình ảnh với hình ảnh được tải xuống từ ajaxload.info với nền trong suốt
Izabela Skibinska

2

Tôi đã sử dụng như sau với Hộp thoại UI UI. (Có lẽ nó hoạt động với các cuộc gọi lại ajax khác?)

$('<div><img src="/i/loading.gif" id="loading" /></div>').load('/ajax.html').dialog({
    height: 300,
    width: 600,
    title: 'Wait for it...'
});

Có chứa một gif tải hoạt hình cho đến khi nội dung của nó được thay thế khi cuộc gọi ajax hoàn thành.


2

Đây là cách tốt nhất cho tôi:

jQuery :

$(document).ajaxStart(function() {
  $(".loading").show();
});

$(document).ajaxStop(function() {
  $(".loading").hide();
});

Cà phê :

  $(document).ajaxStart ->
    $(".loading").show()

  $(document).ajaxStop ->
    $(".loading").hide()

Tài liệu: ajaxStart , ajaxStop


Phải, và bạn có thể sử dụng nó cùng với plugin được đề cập trong câu trả lời này nếu bạn muốn ...
Matt

2

JavaScript

$.listen('click', '#captcha', function() {
    $('#captcha-block').html('<div id="loading" style="width: 70px; height: 40px; display: inline-block;" />');
    $.get("/captcha/new", null, function(data) {
        $('#captcha-block').html(data);
    }); 
    return false;
});

CSS

#loading { background: url(/image/loading.gif) no-repeat center; }

2

Đây là một plugin rất đơn giản và thông minh cho mục đích cụ thể đó: https://github.com/hekigan/is-loading


Thực sự tốt đẹp! Đặc biệt nếu bạn xem các bản demo ... Tắt các thành phần DOM, Trong thẻ, Lớp phủ đầy đủ, Lớp phủ phần tử ... nó sẽ cung cấp mọi thứ bạn cần. Và bạn có thể dễ dàng kết hợp Full Overlay với câu trả lời này để khiến nó hoạt động ngay lập tức.
Matt

1

Tôi làm việc này:

var preloaderdiv = '<div class="thumbs_preloader">Loading...</div>';
           $('#detail_thumbnails').html(preloaderdiv);
             $.ajax({
                        async:true,
                        url:'./Ajaxification/getRandomUser?top='+ $(sender).css('top') +'&lef='+ $(sender).css('left'),
                        success:function(data){
                            $('#detail_thumbnails').html(data);
                        }
             });

1

Tôi nghĩ bạn đúng. Phương pháp này quá toàn cầu ...

Tuy nhiên - đó là một mặc định tốt khi cuộc gọi AJAX của bạn không có hiệu lực trên chính trang đó. (lưu nền chẳng hạn). (bạn luôn có thể tắt nó cho một cuộc gọi ajax nào đó bằng cách chuyển "global": false - xem tài liệu tại jquery

Khi cuộc gọi AJAX có nghĩa là làm mới một phần của trang, tôi thích hình ảnh "đang tải" của mình được dành riêng cho phần được làm mới. Tôi muốn xem phần nào được làm mới.

Hãy tưởng tượng nó sẽ tuyệt như thế nào nếu bạn có thể chỉ cần viết một cái gì đó như:

$("#component_to_refresh").ajax( { ... } ); 

Và điều này sẽ hiển thị một "tải" trên phần này. Dưới đây là một chức năng tôi đã viết xử lý hiển thị "đang tải" nhưng nó dành riêng cho khu vực bạn đang làm mới trong ajax.

Trước tiên, hãy để tôi chỉ cho bạn cách sử dụng nó

<!-- assume you have this HTML and you would like to refresh 
      it / load the content with ajax -->

<span id="email" name="name" class="ajax-loading">
</span>

<!-- then you have the following javascript --> 

$(document).ready(function(){
     $("#email").ajax({'url':"/my/url", load:true, global:false});
 })

Và đây là chức năng - một khởi đầu cơ bản mà bạn có thể nâng cao theo ý muốn. nó rất linh hoạt

jQuery.fn.ajax = function(options)
{
    var $this = $(this);
    debugger;
    function invokeFunc(func, arguments)
    {
        if ( typeof(func) == "function")
        {
            func( arguments ) ;
        }
    }

    function _think( obj, think )
    {
        if ( think )
        {
            obj.html('<div class="loading" style="background: url(/public/images/loading_1.gif) no-repeat; display:inline-block; width:70px; height:30px; padding-left:25px;"> Loading ... </div>');
        }
        else
        {
            obj.find(".loading").hide();
        }
    }

    function makeMeThink( think )
    {
        if ( $this.is(".ajax-loading") )
        {
            _think($this,think);
        }
        else
        {
            _think($this, think);
        }
    }

    options = $.extend({}, options); // make options not null - ridiculous, but still.
    // read more about ajax events
    var newoptions = $.extend({
        beforeSend: function()
        {
            invokeFunc(options.beforeSend, null);
            makeMeThink(true);
        },

        complete: function()
        {
            invokeFunc(options.complete);
            makeMeThink(false);
        },
        success:function(result)
        {
            invokeFunc(options.success);
            if ( options.load )
            {
                $this.html(result);
            }
        }

    }, options);

    $.ajax(newoptions);
};


1

Nếu bạn có kế hoạch sử dụng trình tải mỗi khi bạn thực hiện yêu cầu máy chủ, bạn có thể sử dụng mẫu sau.

 jTarget.ajaxloader(); // (re)start the loader
 $.post('/libs/jajaxloader/demo/service/service.php', function (content) {
     jTarget.append(content); // or do something with the content
 })
 .always(function () {
     jTarget.ajaxloader("stop");
 });

Mã này đặc biệt sử dụng plugin jajaxloader (mà tôi vừa tạo)

https://github.com/lingtalfi/JAjaxLoader/


1

Mã ajax của tôi trông như thế này, thực tế, tôi vừa nhận xét async: false line và spinner xuất hiện.

$.ajax({
        url: "@Url.Action("MyJsonAction", "Home")",
        type: "POST",
        dataType: "json",
        data: {parameter:variable},
        //async: false, 

        error: function () {
        },

        success: function (data) {
          if (Object.keys(data).length > 0) {
          //use data 
          }
          $('#ajaxspinner').hide();
        }
      });

Tôi đang hiển thị spinner trong một hàm trước mã ajax:

$("#MyDropDownID").change(function () {
        $('#ajaxspinner').show();

Đối với Html, tôi đã sử dụng một lớp phông chữ tuyệt vời:

<i id="ajaxspinner" class="fas fa-spinner fa-spin fa-3x fa-fw" style="display:none"></i>

Hy vọng nó sẽ giúp được ai đó.


0

Bạn luôn có thể sử dụng plugin Block UI jQuery để thực hiện mọi thứ cho bạn và thậm chí nó còn chặn trang của bất kỳ đầu vào nào trong khi ajax đang tải. Trong trường hợp plugin dường như không hoạt động, bạn có thể đọc về cách sử dụng đúng trong câu trả lời này. Kiểm tra nó ra.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.