jQuery在慢速操作期间显示“加载”

时间:2009-08-10 06:37:30

标签: jquery performance show-hide

我正在尝试使用jQuery在慢速操作期间显示一个小的加载图像,并且无法正确使用它。 这是一张有数千行的大表。当我选中“mostrarArticulosDeReferencia”复选框时,它会从这些行中删除“隐藏”类。此操作需要几秒钟,我想提供一些反馈。 “loading”是一个带有小动画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在瞬间显示
  5. 更新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()更快,所以不需要加载动画...
    这篇文章向我展示了光:show/hide performance

10 个答案:

答案 0 :(得分:3)

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

  1. jQuery告诉浏览器显示/隐藏加载div
  2. jQuery告诉浏览器添加/删除行中隐藏的类
  3. jQuery告诉浏览器显示/隐藏加载div
  4. 浏览器以错误的顺序执行上述所有步骤(首先是2个)
  5. 我上次更新中的

    'setTimeout'强制浏览器以正确的顺序执行所有步骤。 它很糟糕,不优雅,但至少它有效......

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

答案 1 :(得分: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();
});

答案 2 :(得分:1)

我想你想要做

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

在show的回调函数中。

请查看此处的方法文档:http://docs.jquery.com/Effects/show

通过调用show(0);

,您可以达到相同的“即时显示”效果

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

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

简单! :)

答案 3 :(得分:1)

只是一个注释 - 我已经开发了一个plugin来创建一个带有加载图形的叠加div。

答案 4 :(得分:1)

在页面上放置一个div,如下所示:

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

然后挂钩show并隐藏到ajaxStart,ajaxStop和ajaxError事件,如下所示:

$("#spinner").bind("ajaxSend", function() { $(this).show(); })
$("#spinner").bind("ajaxStop", function() { $(this).hide(); })
$("#spinner").bind("ajaxError", function() { $(this).hide(); });

答案 5 :(得分:0)

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

答案 6 :(得分:0)

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

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

实际上并不是那么慢,而是在几毫秒的时间内执行,所以你看不到加载信息,因为它只是在那里很短的时间。

答案 7 :(得分:0)

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

证明这一点的一种方法是隐藏长表并运行相同的代码。它会做同样的事情,但因为表是不可见的,并且不会使整个动作更快。

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

  1. 尝试避免使用表格并转而使用DIV布局。表格呈现缓慢,取决于浏览器,表格可能只有在完全呈现后才可见。
  2. 如果你必须使用表格考虑使用多个表格,例如100行粘在一起。这样,只要重新格式化第一个表,页面就会开始呈现。
  3. 如果一个大表是唯一的方法,并且您知道用户只能看到顶行,您可以执行两次操作,第一次在顶行,第二次在所有行。这是最慢和最不理想的解决方案,但通过在操作中添加jQuery过滤器可以非常容易实现。

答案 8 :(得分:0)

这不回答原始问题,但是对表格本身的类使用CSS规则是否更快:

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

并按如下方式切换显示:

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

答案 9 :(得分: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年前,也许你不再需要它了。