如何在不让可怕的“停止运行此脚本?”的情况下清除内容?对话?

时间:2010-05-27 18:53:04

标签: javascript jquery

在Windows窗体中,某些控件上有一个BeginUpdate / EndUpdate对。我想要这样的东西,但是对于jQuery。


我有一个div,它有一个div。像这样:

<div id='reportHolder' class='column'>
  <div id='report'> </div>
</div>

在内部div中,我添加了一对(7-12)a和div元素对,如下所示:

<h4><a>Heading1</a></h4>
<div> ...content here....</div>

内容的总大小,可能是200k。每个div只包含一个HTML片段。在其中,有许多<span>个元素,包含其他html元素,并且它们可以嵌套到5-8级深度。没有什么特别的,我不认为。 (更新:使用this answer,我了解到片段中有139423个元素。)

添加完所有内容后, 然后我创造了一个手风琴。像这样:

$('#report').accordion({collapsible:true, active:false});

一切正常。

问题是,当我尝试清除或删除报告div时,需要花费很多时间,我会得到3或4个弹出窗口,询问“你想停止运行这个脚本吗?”

我尝试了几种方法:

选项1:

    $('#report').accordion('destroy');
    $('#report').remove();
    $("#reportHolder").html("<div id='report'> </div>");

选项2:

    $('#report').accordion('destroy');
    $('#report').html('');
    $("#reportHolder").html("<div id='report'> </div>");

选项3:

    $('#report').accordion('destroy');
    $("#reportHolder").html("<div id='report'> </div>");

在评论中得到建议后,我也试过了:

选项4:

    $('#report').accordion('destroy');
    $('#report').empty();
    $("#reportHolder").html("<div id='report'> </div>");

无论如何,它会挂起很长一段时间。

对手风琴的调用('destroy')似乎不是延迟的根源。这是报告div中的html内容的擦除。

这是jQuery 1.3.2。

编辑 - 修正代码拼写错误。

ps:这种情况发生在FF3.5以及IE8上。


问题:

  1. 花了这么长时间?

  2. 如何更快地删除内容?


  3. 附录

    我在“选项4”中突破了FF中的调试器,我看到的堆栈跟踪是:

    data()
    trigger()
    triggerHandler()
    add()
    each()
    each()
    add()
    empty()
    each()
    each()
    (?)()    // <<-- this is the call to empty()
    ResetUi()  // <<-- my code
    onclick
    

    我不明白为什么add()在堆栈中。我正在删除内容,而不是添加内容。我担心在remove(all)的上下文中,jQuery做了一些天真的事情。就像它抓取html内容一样,文本替换为删除一个html元素,然后调用.add()来放回剩下的内容。

    有没有办法告诉jQuery在从dom中删除HTML内容时不传播事件?

    在Windows窗体中,某些控件上有一个BeginUpdate / EndUpdate对。我想要这样的东西,但是对于jQuery。


    相关


    jquery: fastest DOM insertion ?

2 个答案:

答案 0 :(得分:3)

你应该尝试绕过jQuery并在销毁手风琴后自己清空内容:

$('#report')[0].innerHTML = '';

这会快得多,但可能会导致IE泄漏内存(jQuery竭尽全力确保没有引用阻止IE进行垃圾收集,这是为什么删除速度太慢的原因之一数据)。

答案 1 :(得分:1)

我很确定这里会显示“为什么”(来自jQuery 1.4.2):

empty: function() {
  for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
    // Remove element nodes and prevent memory leaks
    if ( elem.nodeType === 1 ) {
      jQuery.cleanData( elem.getElementsByTagName("*") );
    }

    // Remove any remaining nodes
    while ( elem.firstChild ) {
      elem.removeChild( elem.firstChild );
    }
  }

  return this;
},

cleanData: function( elems ) {
  var data, id, cache = jQuery.cache,
      special = jQuery.event.special,
      deleteExpando = jQuery.support.deleteExpando;

  for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
    if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {
      continue;
    }

    id = elem[ jQuery.expando ];

    if ( id ) {
      data = cache[ id ];

      if ( data && data.events ) {
        for ( var type in data.events ) {
          if ( special[ type ] ) {
            jQuery.event.remove( elem, type );
          } else {
            removeEvent( elem, type, data.handle );
          }
        }
      }

      if ( deleteExpando ) {
        delete elem[ jQuery.expando ];
      } else if ( elem.removeAttribute ) {
        elem.removeAttribute( jQuery.expando );
      }

      delete cache[ id ];
    }
  }
}

请注意,empty()函数(以及删除DOM元素的任何其他内容)将调用cleanData(),它会扫描每个包含的节点以删除expando属性并取消绑定绑定的事件,删除内部缓存中的所有数据,以及不存在的数据。

你也许可以通过分解工作来解决这个问题。我不确定你在这个元素中有多少孩子,但你可以尝试这样的事情:

$('#report').children().each(function() {
  var $this = $(this); 
  setTimeout(function() { $this.remove(); }, 0);
});

假设有10个#report的直接子项,这会将删除操作拆分为10个单独的事件循环,这可能会解决您的长处理延迟问题。