在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上。
问题:
花了这么长时间?
如何更快地删除内容?
附录
我在“选项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。
答案 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个单独的事件循环,这可能会解决您的长处理延迟问题。