Câu trả lời:
Bạn có thể làm điều này nhiều cách khác nhau. Nó có thể là một trạng thái tinh tế như một trạng thái nhỏ trên trang có nội dung "Đang tải ..." hoặc lớn như toàn bộ phần tử làm xám trang trong khi dữ liệu mới đang tải. Cách tiếp cận tôi đang thực hiện dưới đây sẽ chỉ cho bạn cách thực hiện cả hai phương pháp.
Hãy bắt đầu bằng cách cho chúng tôi một hình ảnh động "tải" đẹp từ http://ajaxload.info Tôi sẽ sử dụng
Hãy tạo một yếu tố mà chúng tôi có thể hiển thị / ẩn bất cứ khi nào chúng tôi thực hiện yêu cầu ajax:
<div class="modal"><!-- Place at bottom of page --></div>
Tiếp theo hãy cho nó một chút tinh tế:
/* Start by setting display:none to make this hidden.
Then we position it in relation to the viewport window
with position:fixed. Width, height, top and left speak
for themselves. Background we set to 80% white with
our animation centered, and no-repeating */
.modal {
display: none;
position: fixed;
z-index: 1000;
top: 0;
left: 0;
height: 100%;
width: 100%;
background: rgba( 255, 255, 255, .8 )
url('http://i.stack.imgur.com/FhHRx.gif')
50% 50%
no-repeat;
}
/* When the body has the loading class, we turn
the scrollbar off with overflow:hidden */
body.loading .modal {
overflow: hidden;
}
/* Anytime the body has the loading class, our
modal element will be visible */
body.loading .modal {
display: block;
}
Được rồi, vào jQuery. Phần tiếp theo này thực sự rất đơn giản:
$body = $("body");
$(document).on({
ajaxStart: function() { $body.addClass("loading"); },
ajaxStop: function() { $body.removeClass("loading"); }
});
Đó là nó! Chúng tôi đang gắn một số sự kiện vào yếu tố cơ thể bất cứ khi nào ajaxStart
hoặc ajaxStop
sự kiện được kích hoạt. Khi một sự kiện ajax bắt đầu, chúng ta thêm lớp "nạp" vào phần thân. và khi các sự kiện được thực hiện, chúng ta loại bỏ lớp "nạp" khỏi phần thân.
Xem nó trong hành động: http://jsfiddle.net/VpDUG/4952/
.ajaxStop()
và .ajaxStart()
chỉ nên được đính kèm vào tài liệu. tài liệu
Theo như hình ảnh tải thực tế, hãy xem trang web này để biết một loạt các tùy chọn.
Theo như hiển thị DIV với hình ảnh này khi yêu cầu bắt đầu, bạn có một vài lựa chọn:
A) Hiển thị thủ công và ẩn hình ảnh:
$('#form').submit(function() {
$('#wait').show();
$.post('/whatever.php', function() {
$('#wait').hide();
});
return false;
});
B) Sử dụng ajaxStart và ajaxComplete :
$('#wait').ajaxStart(function() {
$(this).show();
}).ajaxComplete(function() {
$(this).hide();
});
Sử dụng phần tử này sẽ hiển thị / ẩn cho bất kỳ yêu cầu. Có thể là tốt hay xấu, tùy thuộc vào nhu cầu.
C) Sử dụng các cuộc gọi lại riêng lẻ cho một yêu cầu cụ thể:
$('#form').submit(function() {
$.ajax({
url: '/whatever.php',
beforeSend: function() { $('#wait').show(); },
complete: function() { $('#wait').hide(); }
});
return false;
});
Cùng với những gì Jonathan và Samir đề xuất (cả hai câu trả lời xuất sắc btw!), JQuery có một số sự kiện được xây dựng mà nó sẽ kích hoạt cho bạn khi đưa ra yêu cầu ajax.
Có ajaxStart
sự kiện
Hiển thị thông báo tải bất cứ khi nào yêu cầu AJAX bắt đầu (và không có yêu cầu nào đang hoạt động).
... và đó là anh trai, ajaxStop
sự kiện
Đính kèm một chức năng để được thực thi bất cứ khi nào tất cả các yêu cầu AJAX kết thúc. Đây là một sự kiện Ajax.
Cùng nhau, họ thực hiện một cách tốt để hiển thị thông báo tiến trình khi bất kỳ hoạt động ajax nào đang diễn ra ở bất cứ đâu trên trang.
HTML:
<div id="loading">
<p><img src="loading.gif" /> Please Wait</p>
</div>
Kịch bản:
$(document).ajaxStart(function(){
$('#loading').show();
}).ajaxStop(function(){
$('#loading').hide();
});
.ajaxStart
chỉ có thể được đính kèm vào tài liệu, tức là. $(document).ajaxStart(function(){}).
Bạn có thể lấy một GIF hoạt hình của một vòng tròn quay từ Ajaxload - dán ở đâu đó trong chế độ gia truyền tệp trang web của bạn. Sau đó, bạn chỉ cần thêm một phần tử HTML với mã chính xác và xóa phần tử đó khi bạn hoàn tất. Điều này khá đơn giản:
function showLoadingImage() {
$('#yourParentElement').append('<div id="loading-image"><img src="path/to/loading.gif" alt="Loading..." /></div>');
}
function hideLoadingImage() {
$('#loading-image').remove();
}
Sau đó, bạn chỉ cần sử dụng các phương thức này trong cuộc gọi AJAX của mình:
$.load(
'http://example.com/myurl',
{ 'random': 'data': 1: 2, 'dwarfs': 7},
function (responseText, textStatus, XMLHttpRequest) {
hideLoadingImage();
}
);
// this will be run immediately after the AJAX call has been made,
// not when it completes.
showLoadingImage();
Điều này có một vài lưu ý: trước hết, nếu bạn có hai hoặc nhiều địa điểm tải hình ảnh có thể được hiển thị, bạn sẽ cần phải theo dõi xem có bao nhiêu cuộc gọi đang chạy cùng một lúc và chỉ ẩn khi chúng tất cả đã được làm xong. Điều này có thể được thực hiện bằng cách sử dụng một bộ đếm đơn giản, sẽ hoạt động cho hầu hết các trường hợp.
Thứ hai, điều này sẽ chỉ ẩn hình ảnh tải trên một cuộc gọi AJAX thành công. Để xử lý các trạng thái lỗi, bạn sẽ cần phải nhìn vào $.ajax
, đó là phức tạp hơn $.load
, $.get
và như thế, nhưng rất nhiều linh hoạt hơn nữa.
showLoadingImage
trước khi bạn bắt đầu và hideLoadingImage
sau khi bạn kết thúc. Nên khá đơn giản. Bạn có thể cần phải thực hiện một số loại setTimeout
cuộc gọi để đảm bảo trình duyệt thực sự hiển thị <img>
thẻ mới - tôi đã thấy một vài trường hợp không thực hiện được cho đến khi JavaScript thực thi xong.
Giải pháp tuyệt vời của Jonathon phá vỡ trong IE8 (hoạt hình hoàn toàn không hiển thị). Để khắc phục điều này, hãy thay đổi CSS thành:
.modal {
display: none;
position: fixed;
z-index: 1000;
top: 0;
left: 0;
height: 100%;
width: 100%;
background: rgba( 255, 255, 255, .8 )
url('http://i.stack.imgur.com/FhHRx.gif')
50% 50%
no-repeat;
opacity: 0.80;
-ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity = 80);
filter: alpha(opacity = 80)};
jQuery cung cấp các hook sự kiện khi các yêu cầu AJAX bắt đầu và kết thúc. Bạn có thể móc vào những cái này để hiển thị trình tải của bạn.
Ví dụ: tạo div sau:
<div id="spinner">
<img src="images/spinner.gif" alt="Loading" />
</div>
Đặt nó vào display: none
trong bảng định kiểu của bạn. Bạn có thể tạo kiểu theo bất cứ cách nào bạn muốn. Bạn có thể tạo một hình ảnh tải đẹp tại Ajaxload.info , nếu bạn muốn.
Sau đó, bạn có thể sử dụng một cái gì đó như sau để làm cho nó được hiển thị tự động khi gửi các yêu cầu Ajax:
$(document).ready(function () {
$('#spinner').bind("ajaxSend", function() {
$(this).show();
}).bind("ajaxComplete", function() {
$(this).hide();
});
});
Chỉ cần thêm khối Javascript này vào cuối trang của bạn trước đóng thẻ cơ thể hoặc bất cứ nơi nào bạn thấy phù hợp.
Bây giờ, bất cứ khi nào bạn gửi yêu cầu Ajax, #spinner
div sẽ được hiển thị. Khi yêu cầu hoàn thành, nó sẽ được ẩn lại.
Nếu bạn đang sử dụng Turbolinks With Rails thì đây là giải pháp của tôi:
Đây là CoffeeScript
$(window).on 'page:fetch', ->
$('body').append("<div class='modal'></div>")
$('body').addClass("loading")
$(window).on 'page:change', ->
$('body').removeClass("loading")
Đây là CSS SASS dựa trên câu trả lời xuất sắc đầu tiên từ Jonathan Sampson
# loader.css.scss
.modal {
display: none;
position: fixed;
z-index: 1000;
top: 0;
left: 0;
height: 100%;
width: 100%;
background: rgba( 255, 255, 255, 0.4)
asset-url('ajax-loader.gif', image)
50% 50%
no-repeat;
}
body.loading {
overflow: hidden;
}
body.loading .modal {
display: block;
}
Giống như Mark H đã nói blockUI là cách.
Ví dụ.:
<script type="text/javascript" src="javascript/jquery/jquery.blockUI.js"></script>
<script>
// unblock when ajax activity stops
$(document).ajaxStop($.unblockUI);
$("#downloadButton").click(function() {
$("#dialog").dialog({
width:"390px",
modal:true,
buttons: {
"OK, AGUARDO O E-MAIL!": function() {
$.blockUI({ message: '<img src="img/ajax-loader.gif" />' });
send();
}
}
});
});
function send() {
$.ajax({
url: "download-enviar.do",
type: "POST",
blablabla
});
}
</script>
Quan sát: Tôi đã nhận được ajax-loader.gif trên http://www.ajaxload.info/
Với tất cả sự tôn trọng đối với các bài đăng khác, bạn có ở đây một giải pháp rất đơn giản, sử dụng CSS3 và jQuery, mà không cần sử dụng bất kỳ tài nguyên bên ngoài cũng như các tệp nào.
$('#submit').click(function(){
$(this).addClass('button_loader').attr("value","");
window.setTimeout(function(){
$('#submit').removeClass('button_loader').attr("value","\u2713");
$('#submit').prop('disabled', true);
}, 3000);
});
#submit:focus{
outline:none;
outline-offset: none;
}
.button {
display: inline-block;
padding: 6px 12px;
margin: 20px 8px;
font-size: 14px;
font-weight: 400;
line-height: 1.42857143;
text-align: center;
white-space: nowrap;
vertical-align: middle;
-ms-touch-action: manipulation;
cursor: pointer;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
background-image: none;
border: 2px solid transparent;
border-radius: 5px;
color: #000;
background-color: #b2b2b2;
border-color: #969696;
}
.button_loader {
background-color: transparent;
border: 4px solid #f3f3f3;
border-radius: 50%;
border-top: 4px solid #969696;
border-bottom: 4px solid #969696;
width: 35px;
height: 35px;
-webkit-animation: spin 0.8s linear infinite;
animation: spin 0.8s linear infinite;
}
@-webkit-keyframes spin {
0% { -webkit-transform: rotate(0deg); }
99% { -webkit-transform: rotate(360deg); }
}
@keyframes spin {
0% { transform: rotate(0deg); }
99% { transform: rotate(360deg); }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="submit" class="button" type="submit" value="Submit" />
Điều này sẽ làm cho các nút biến mất, sau đó một hình ảnh động "tải" sẽ xuất hiện ở vị trí của chúng và cuối cùng chỉ hiển thị một thông báo thành công.
$(function(){
$('#submit').click(function(){
$('#submit').hide();
$("#form .buttons").append('<img src="assets/img/loading.gif" alt="Loading..." id="loading" />');
$.post("sendmail.php",
{emailFrom: nameVal, subject: subjectVal, message: messageVal},
function(data){
jQuery("#form").slideUp("normal", function() {
$("#form").before('<h1>Success</h1><p>Your email was sent.</p>');
});
}
);
});
});
Hầu hết các giải pháp tôi đã thấy đều mong muốn chúng tôi thiết kế lớp phủ tải, giữ ẩn và sau đó bỏ ẩn khi cần, hoặc hiển thị ảnh gif hoặc hình ảnh, v.v.
Tôi muốn phát triển một plugin mạnh mẽ, trong đó với một lệnh gọi jQuery đơn giản, tôi có thể hiển thị màn hình tải và xé nó khi nhiệm vụ hoàn thành.
Dưới đây là mã. Nó phụ thuộc vào Font awesome và jQuery:
/**
* Raj: Used basic sources from here: http://jsfiddle.net/eys3d/741/
**/
(function($){
// Retain count concept: http://stackoverflow.com/a/2420247/260665
// Callers should make sure that for every invocation of loadingSpinner method there has to be an equivalent invocation of removeLoadingSpinner
var retainCount = 0;
// http://stackoverflow.com/a/13992290/260665 difference between $.fn.extend and $.extend
$.extend({
loadingSpinner: function() {
// add the overlay with loading image to the page
var over = '<div id="custom-loading-overlay">' +
'<i id="custom-loading" class="fa fa-spinner fa-spin fa-3x fa-fw" style="font-size:48px; color: #470A68;"></i>'+
'</div>';
if (0===retainCount) {
$(over).appendTo('body');
}
retainCount++;
},
removeLoadingSpinner: function() {
retainCount--;
if (retainCount<=0) {
$('#custom-loading-overlay').remove();
retainCount = 0;
}
}
});
}(jQuery));
Chỉ cần đặt ở trên trong một tập tin js và bao gồm nó trong suốt dự án.
Bổ sung CSS:
#custom-loading-overlay {
position: absolute;
left: 0;
top: 0;
bottom: 0;
right: 0;
background: #000;
opacity: 0.8;
filter: alpha(opacity=80);
}
#custom-loading {
width: 50px;
height: 57px;
position: absolute;
top: 50%;
left: 50%;
margin: -28px 0 0 -25px;
}
Cầu nguyện:
$.loadingSpinner();
$.removeLoadingSpinner();
Lưu ý rằng khi sử dụng ASP.Net MVC, với using (Ajax.BeginForm(...
, hãy đặtajaxStart
sẽ không hoạt động.
Sử dụng AjaxOptions
để khắc phục vấn đề này:
(Ajax.BeginForm("ActionName", new AjaxOptions { OnBegin = "uiOfProccessingAjaxAction", OnComplete = "uiOfProccessingAjaxActionComplete" }))
Mỗi https://www.w3schools.com/howto/howto_css_loader.asp , đây là quy trình gồm 2 bước không có JS:
1.Thêm HTML này vào nơi bạn muốn spinner: <div class="loader"></div>
2.Thêm CSS này để tạo spinner thực tế:
.loader {
border: 16px solid #f3f3f3; /* Light grey */
border-top: 16px solid #3498db; /* Blue */
border-radius: 50%;
width: 120px;
height: 120px;
animation: spin 2s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
$("#loader").toggle();
trước khi thực hiện yêu cầu chạy dài để bắt đầu hoạt hình và thực hiện một cuộc gọi khác trong chức năng gọi lại của yêu cầu để ẩn nó đi.
Tôi sử dụng CSS3 cho hoạt hình
/************ CSS3 *************/
.icon-spin {
font-size: 1.5em;
display: inline-block;
animation: spin1 2s infinite linear;
}
@keyframes spin1{
0%{transform:rotate(0deg)}
100%{transform:rotate(359deg)}
}
/************** CSS3 cross-platform ******************/
.icon-spin-cross-platform {
font-size: 1.5em;
display: inline-block;
-moz-animation: spin 2s infinite linear;
-o-animation: spin 2s infinite linear;
-webkit-animation: spin 2s infinite linear;
animation: spin2 2s infinite linear;
}
@keyframes spin2{
0%{transform:rotate(0deg)}
100%{transform:rotate(359deg)}
}
@-moz-keyframes spin2{
0%{-moz-transform:rotate(0deg)}
100%{-moz-transform:rotate(359deg)}
}
@-webkit-keyframes spin2{
0%{-webkit-transform:rotate(0deg)}
100%{-webkit-transform:rotate(359deg)}
}
@-o-keyframes spin2{
0%{-o-transform:rotate(0deg)}
100%{-o-transform:rotate(359deg)}
}
@-ms-keyframes spin2{
0%{-ms-transform:rotate(0deg)}
100%{-ms-transform:rotate(359deg)}
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<div class="row">
<div class="col-md-6">
Default CSS3
<span class="glyphicon glyphicon-repeat icon-spin"></span>
</div>
<div class="col-md-6">
Cross-Platform CSS3
<span class="glyphicon glyphicon-repeat icon-spin-cross-platform"></span>
</div>
</div>