8

我试图在使用 jQuery 的缓慢操作期间显示一个小的加载图像,但无法正确处理。这是一个有数千行的大表。当我选中“mostrarArticulosDeReferencia”复选框时,它会从这些行中删除“隐藏”类。此操作需要几秒钟,我想提供一些反馈。“正在加载”是一个带有小动画 gif 的 div

这是完整的代码

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。有任何想法吗?

奖励:有更快的方法来做这个显示/隐藏的事情吗?发现切换速度慢得多。

更新:我试过这个

    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() 快得多,所以不需要加载动画......
这篇文章向我展示了光:显示/隐藏性能

4

10 回答 10

3

我尝试了一切,我不得不得出结论,这是浏览器脑残的产物。

  1. jQuery 告诉浏览器显示/隐藏正在加载的 div
  2. jQuery 告诉浏览器从行中添加/删除隐藏类
  3. jQuery 告诉浏览器显示/隐藏正在加载的 div
  4. 浏览器以错误的顺序执行上述所有步骤(第 2 个)

我上次更新中的“setTimeout”强制浏览器以正确的顺序执行所有步骤。它很烂,不优雅,但至少它有效......

更新: setTimeout 是必要的,因为 jquery “简化”了命令链。如果我告诉它隐藏一个元素并再次显示它,它会简单地忽略该命令,因为最终结果将与什么都不做......

于 2009-09-20T03:50:57.007 回答
3

显然,在“长时间运行的过程”期间,您正在触发一个异步请求(是的,异步,换句话说,它不会与代码同步运行!)。您需要$('#loading').hide()在异步请求的回调函数结束时调用。

这是一个很好的例子:

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

这显然行不通。它会显示,触发一个异步请求,然后立即隐藏。您需要将代码重写为:

$('#loading').show();
$.getJSON('someURL', function(data) {
    // Do slow processing.
    $('#loading').hide();
});
于 2010-03-17T17:35:43.837 回答
1

我想你想做

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

在显示的回调函数中。

在这里查看方法文档:http: //docs.jquery.com/Effects/show

您可以通过调用实现相同的“即时显示”效果show(0);

但是你想做回调吗?没问题,这样做:

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

简单的!:)

于 2009-08-10T08:23:01.760 回答
1

请注意 - 我开发了一个插件,用于创建一个包含加载图形的覆盖 div。

于 2010-07-18T16:05:52.940 回答
1

在您的页面上放置一个 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(); });
于 2012-03-13T22:05:04.690 回答
0

您是否尝试过使用ajaxStart来运行更新功能?

于 2009-08-10T06:45:48.460 回答
0

我认为它工作正常。这个操作:

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

并没有那么慢,它在几毫秒内执行,所以你看不到加载信息,因为它只存在很短的时间。

于 2009-08-10T06:47:38.253 回答
0

我也看到过这种行为,它取决于所使用的浏览器。IE 是受影响最大的一个。原因不是 jQuery 慢,虽然 JavaScript 在 IE 中运行速度较慢,但​​更多是由于新 HTML 的呈现。setTimeout() 有帮助的原因是它执行第一个操作,并且只有在浏览器完成渲染新 HTML 时,第二部分才完成。整个操作实际上更慢,但反馈使它更好。

证明这一点的一种方法是隐藏长表并运行相同的代码。它会做同样的事情,但是由于表格是不可见的并且不会渲染整个动作,所以速度要快得多。

有几种方法可以解决这个问题。

  1. 尽量避免使用表格并改为使用 DIV 布局。表格呈现缓慢,并且根据浏览器的不同,表格可能只会变得可见然后完全呈现。
  2. 如果您必须使用表,请考虑使用多个表,例如 100 行粘在一起。这样,一旦第一个表被重新格式化,页面就会开始呈现。
  3. 如果一个大表是唯一的方法,并且您知道用户只能看到顶行,您可以执行两次操作,第一次在顶行上,第二次在所有行上。这是最慢且最不理想的解决方案,但可以通过在操作中添加 jQuery 过滤器来轻松实现。
于 2009-08-10T08:23:10.417 回答
0

这并没有回答最初的问题,但是对表本身的类使用 CSS 规则是否更快:

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

并像这样切换显示:

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

?

于 2010-03-17T17:28:03.733 回答
0

尝试使用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 请求执行此操作的正确方法(我想这将对某人有用)是使用ajaxStartajaxStop ,如下所示:

$(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 年前,也许你不再需要这个了。

于 2013-02-02T03:49:38.600 回答