以下HTML和JavaScript取自此jsFiddle的部分内容: http://jsfiddle.net/stephenjwatkins/2j3ZB/3/
HTML:
<p class="source">
Source
</p>
<div id="target">
<p class="dummy">
Target
</p>
</div>
<button id="transfer-button">Transfer</button>
JavaScript的:
var sourceEl = $('.source');
var targetEl = $('#target');
$('#transfer-button').click(function() {
targetEl.html('<p class="dummy">Transferring...</p>');
setTimeout(function() {
// Source element will be empty on second attempt to append
targetEl.html('').append(sourceEl);
}, 750);
return false;
});
请注意,setTimeout和虚拟文本仅用于视觉指示器。
可以看出,在从DOM添加和删除源元素之后,IE(所有版本)将在任何进一步追加时向DOM添加空元素;而所有其他浏览器都会添加正确的非空元素。
另一个令人困惑的方面是sourceEl仍然有元素信息(例如sourceEl.attr('class')
将返回&#34; source&#34;)。
我知道缓解这个问题的方法(例如sourceEl.clone()
),但是如果能够更好地理解为什么IE的行为方式不同以避免将来出现任何相关问题,那将会很好。
在替换元素后,导致元素在IE中唯一为空的原因是什么?
答案 0 :(得分:6)
首先让我们重点介绍一下重要部分:
source
元素并将其放在target
元素内; target
元素,并向其中添加一个新子项(p.dummy
),从DOM中有效删除source
; target
元素,并尝试重新附加source
,该内容已不再存在于DOM中。初看起来,这不适用于任何浏览器,因为source
元素已从DOM中删除。这里的“神奇”是JavaScript的Garbage Collector。浏览器看到sourceEl
仍然是作用域的(在setTimeout
闭包内)并且不会将引用的DOM元素遗留在sourceEl
jQuery对象中。
这里的问题不是JScript(Microsft的Javascript实现)的垃圾收集器,而是JScript在设置元素innerHTML
时如何处理DOM解析。
其他浏览器将简单地分离所有childNode
(当没有更多活动引用时将由GC收集它们)并将传递的html字符串解析为DOM元素,并将它们附加到DOM。另一方面,Jscript也会删除分离的childNode
s'innerHTML
/ childNode
。请查看此fiddle以获取说明。
事实上,该元素在IE中仍然存在并附加到DOM:
它再也没有childNode
了。
要防止出现此类行为,.clone()
元素(如问题中所述)或.detach()
之前,如果您打算重新使用其父级,请先调用.html()
元素而不是“覆盖”它。
在覆盖元素之前使用.detach()
fiddle,在所有浏览器中都能正常使用。
答案 1 :(得分:2)
在我看来,IE的行为正常,而其他浏览器对于工作来说是神奇的。 这一切都源于你打电话的时候:
targetEl.html('<p class="dummy">Transferring...</p>');
这将从页面中删除sourceEl
元素。所以它不再存在。我猜其他浏览器正在记住DOM对象,因为仍然有一个引用它的变量。但IE认为这不再存在于页面上,因此它失去了参考。
正如您所提到的,我建议您在点击时克隆该对象。这将在JavaScript中创建一个新对象。幸运的是,覆盖相同的变量是有效的。
sourceEl = sourceEl.clone();
编辑您还可以在插入新的原始源对象之前删除它们。这解决了触发快乐答题器的问题:
setTimeout(function() {
$('.source').remove();
targetEl.html('').append(sourceEl);
}, 750);