JQuery показать «загрузка» во время медленной работы - PullRequest
7 голосов
/ 10 августа 2009

Я пытаюсь показать маленькое изображение загрузки во время медленной работы с jQuery и не могу сделать это правильно. Это большая таблица с тысячами строк. Когда я проверяю флажок «mostrarArticulosDeReferencia», он удаляет «скрытый» класс из этих строк. Эта операция занимает пару секунд, и я хочу дать некоторые отзывы. «загрузка» - это div с небольшим анимированным GIF

Вот полный код

jQuery(document).ready(function() {
jQuery("#mostrarArticulosDeReferencia").click(function(event){
    if( jQuery("#mostrarArticulosDeReferencia").attr("checked") ) {
        jQuery("#loading").show(); //not showing
        jQuery("#listadoArticulos tr.r").removeClass("hidden"); //slow operation
        jQuery("#loading").hide();
    } else {
        jQuery("#loading").show();  //not showing
        jQuery("#listadoArticulos tr.r").addClass("hidden");  //slow operation
        jQuery("#loading").hide();
    }
});
jQuery("#loading").hide();
});

Похоже, jquery "оптимизирует" эти 3 строки

        jQuery("#loading").show(); //not showing
        jQuery("#listadoArticulos tr.r").removeClass("hidden");
        jQuery("#loading").hide();

И никогда не показывает загрузочный div. Есть идеи?

Бонус: Есть более быстрый способ сделать это шоу / скрыть вещь? Выяснилось, что переключение НАМНОГО медленнее.

UPDATE: Я попробовал это

    jQuery("#mostrarArticulosDeReferencia").click(function(event){
    if( jQuery("#mostrarArticulosDeReferencia").attr("checked") ) {
            jQuery("#loading").show(); //not showing
            jQuery("#listadoArticulos tr.r").removeClass("hidden"); //slow operation
            setTimeout("jQuery('#loading').hide()", 1000);
    } else {
            jQuery("#loading").show();  //not showing
            jQuery("#listadoArticulos tr.r").addClass("hidden");  //slow operation
            setTimeout("jQuery('#loading').hide()", 1000);
    }
});

Вот что я получаю

  1. нажмите на флажок
  2. ничего не происходит в течение 2/3 секунд (обработка)
  3. страница обновляется
  4. Загрузка Div отображается в течение доли секунды

ОБНОВЛЕНИЕ 2: У меня есть рабочее решение. Но ПОЧЕМУ я должен использовать setTimeout, чтобы заставить его работать, мне не под силу ...

    jQuery("#mostrarArticulosDeReferencia").click(function(event){
    if( jQuery("#mostrarArticulosDeReferencia").attr("checked") ) {
            jQuery("#loading").show();
            setTimeout("jQuery('#listadoArticulos tr.r').removeClass('hidden');", 1);
            setTimeout("jQuery('#loading').hide()", 1);
    } else {
            jQuery("#loading").show();
            setTimeout("jQuery('#listadoArticulos tr.r').addClass('hidden');", 1);
            setTimeout("jQuery('#loading').hide()", 1);
    }
});

ОБНОВЛЕНИЕ 3: Просто нашел лучшее решение для этого конкретного случая.

//mostrar u ocultar articulos de referencia
$("#mostrarArticulosDeReferencia").click(function(event){
    if( $("#mostrarArticulosDeReferencia").attr("checked") )
        $("tr.r").css({'display':'table-row'});
    else
        $("tr.r").css({'display':'none'});
});

Использование .css ({'display': 'none'}) оказывается намного быстрее, чем hide (), поэтому нет необходимости загружать анимацию ...
Эта статья показала мне свет: Показать / скрыть производительность .

Ответы [ 10 ]

3 голосов
/ 20 сентября 2009

Я попробовал все, и я должен сделать вывод, что это продукт мозгового перенаправления браузера.

  1. jQuery указывает браузеру показать / скрыть загрузочный div
  2. jQuery говорит браузеру добавить / удалить скрытый класс из строк
  3. jQuery говорит браузеру показать / скрыть загрузочный div
  4. Браузер выполняет все вышеперечисленные шаги в неправильном порядке (2 на первом месте)

'setTimeout' в моем последнем обновлении заставляет браузер выполнять все шаги в правильном порядке. Это отстой, не элегантно, но, по крайней мере, это работает ...

Обновление: setTimeout необходим, потому что jquery «упрощает» цепочку команд. Если я скажу ему скрыть один элемент и показать его снова, он просто проигнорирует команду, потому что конечный результат будет таким же, как и ничего не делать ...

3 голосов
/ 17 марта 2010

Очевидно, что вы запускаете асинхронный запрос (да, асинхронный , другими словами, он не выполняется синхронно с кодом!) Во время "длительного процесса" ». Вам необходимо вызвать $('#loading').hide() в конце функции обратного вызова асинхронного запроса.

Вот отличный пример:

$('#loading').show();
$.getJSON('someURL', function(data) {
    // Do slow processing.
});
$('#loading').hide();

Это явно не сработает. Он покажет, запустит асинхронный запрос и сразу же скроет. Вам нужно переписать код как:

$('#loading').show();
$.getJSON('someURL', function(data) {
    // Do slow processing.
    $('#loading').hide();
});
1 голос
/ 14 марта 2012

Поместите div на свою страницу где-то так:

<div id="spinner" class="spinner" style="display:none;">
    <img id="img-spinner" src="@Url.Content("~/images/loading.gif")" alt="Loading"/>
</div>

Затем подключите шоу и спрячьте к событиям ajaxStart, ajaxStop и ajaxError следующим образом:

$("#spinner").bind("ajaxSend", function() { $(this).show(); })
$("#spinner").bind("ajaxStop", function() { $(this).hide(); })
$("#spinner").bind("ajaxError", function() { $(this).hide(); });
1 голос
/ 18 июля 2010

Просто примечание - я разработал плагин для создания оверлея div с загрузочной графикой в ​​нем.

1 голос
/ 10 августа 2009

Я думаю, что вы хотите делать

jQuery("#listadoArticulos tr.r").removeClass("hidden");

внутри функции обратного вызова для шоу.

Посмотрите документацию по методу здесь: http://docs.jquery.com/Effects/show

Вы можете добиться того же эффекта «мгновенного показа», позвонив show(0);

Но вы хотите сделать обратный звонок? Нет проблем, сделайте это:

show(0, function() { jQuery("#listadoArticulos tr.r").removeClass("hidden"); });

Simple! :)

0 голосов
/ 02 февраля 2013

Попробуйте использовать обратный вызов "complete" метода show, js в основном основан на асинхронных событиях, и это три строки:

jQuery("#loading").show(); //not showing
jQuery("#listadoArticulos tr.r").removeClass("hidden");
jQuery("#loading").hide();

будут выполняться без ожидания, поэтому ваше показ, добавление класса и немедленное скрытие div, поэтому вы не можете видеть div, вы скрываете его без ожидания, чтобы его показать, и оно действительно появляется и исчезает быстрый, или даже он может никогда не появиться (не знаю ни о какой оптимизации этого типа).

Если вы добавите два последних в полные обратные вызовы, это будет работать, больше http://api.jquery.com/show/:

jQuery("#loading").show(400, function (){
    jQuery("#listadoArticulos tr.r").removeClass("hidden");
    jQuery("#loading").hide();
});

В любом случае, также, правильный способ сделать это для ajax-запроса (я думаю, это будет полезно для кого-то) - это использовать ajaxStart и ajaxStop , например так:

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

Добавление для removeClass отсутствия обратного вызова:

Возможно, ваша проблема заключалась в том, что для removeClass нет обратного вызова, но вы можете сделать следующее:

jQuery("#loading").show(400, function (){
    var els = jQuery("#listadoArticulos tr.r");
    els.each(function(i, el) {
        el.removeClass("hidden");
        if (els.length == i +1) jQuery("#loading").hide();
    });
});

попробуйте это тоже:

var els = jQuery("#listadoArticulos tr.r");
els.each(function(i, el) {
  if (i == 0) jQuery("#loading").show();
  el.removeClass("hidden");
  if (els.length == i +1) jQuery("#loading").hide();
});

Вы можете добавить проблему, что если у вас есть изображения или любой дополнительный код, который активируется после удаления класса, нет никакого собственного способа ждать, пока они скрывают загрузочный div, так что, возможно, даже если вы удалите скрытый там класс не легко ждать, пока объекты будут видны.

Я просто заметил, что это было 2 года назад, может быть, вам это больше не нужно.

0 голосов
/ 17 марта 2010

Это не отвечает на первоначальный вопрос, но быстрее ли использовать правило CSS для класса в самой таблице:

#listadoArticulos.hideCertainRows tr.r { display: none }

и переключить дисплей следующим образом:

jQuery("#listadoArticulos").addClass("hideCertainRows");

0 голосов
/ 10 августа 2009

Я также видел это поведение, и оно зависит от используемого браузера. IE является наиболее пострадавшим. Причина не в том, что jQuery работает медленно, хотя JavaScript работает медленнее в IE, а больше из-за рендеринга нового HTML. Причина, по которой setTimeout () помогает, заключается в том, что он выполняет первое действие, и только когда браузер завершает рендеринг нового HTML, вторая часть выполняется. Вся операция на самом деле медленнее, но обратная связь делает ее лучше.

Один из способов продемонстрировать это - скрыть длинную таблицу и запустить один и тот же код. Он будет делать то же самое, но поскольку таблица невидима и не отображает, все действие выполняется намного быстрее.

Есть несколько способов обойти это.

  1. Старайтесь избегать таблиц и вместо этого используйте макет DIV. Таблицы визуализируются медленно, и в зависимости от браузера таблица может стать видимой только тогда, когда будет полностью визуализирована.
  2. Если вам необходимо использовать таблицу, рассмотрите возможность использования нескольких таблиц, скажем, 100 строк, соединенных вместе. Таким образом, страница начинает отображаться, как только первая таблица будет переформатирована.
  3. Если одна большая таблица - единственный путь, и вы знаете, что пользователь может видеть только верхние строки, вы можете выполнить действие дважды, первый раз в верхних строках и второй раз во всех строках. Это самое медленное и наименее оптимальное решение, но его очень легко реализовать, добавив в действие фильтр jQuery.
0 голосов
/ 10 августа 2009

Я думаю, что это работает правильно. Эта операция:

jQuery("#listadoArticulos tr.r").removeClass("hidden");

на самом деле не такой медленный и выполняется за несколько мс, так что вы не видите информацию о загрузке, потому что она очень короткая.

0 голосов
/ 10 августа 2009

Вы пытались использовать ajaxStart для запуска функции обновления?

...