从DOM中删除后,为什么IE中的元素为空?

Ste*_*ins 4 javascript jquery internet-explorer dom

以下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>
Run Code Online (Sandbox Code Playgroud)

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;
});?
Run Code Online (Sandbox Code Playgroud)

请注意,setTimeout和虚拟文本仅用于可视指示器.

可以看出,在从DOM添加和删除源元素之后,IE(所有版本)将在任何进一步追加时向DOM添加空元素; 而所有其他浏览器都会添加正确的非空元素.

另一个增加混淆的方面是sourceEl仍然具有元素信息(例如sourceEl.attr('class')将返回"source").

我知道减轻问题的方法(例如sourceEl.clone()),但是如果能够更好地理解为什么IE的行为方式不同以避免将来出现任何相关问题,那将会很好.

一旦替换元素,是什么导致源元素在IE中唯一地为空?

Fab*_*tté 6

首先让我们重点介绍一下重要部分:

  1. (第一次单击)获取source元素并将其放入target元素内;
  2. (第二次单击)清空target元素并向其添加一个新的child(p.dummy),从而有效地source从DOM中删除;
  3. 清空target元素并尝试重新追加source,这在DOM中不再存在.

初看起来,这不适用于任何浏览器,因为该source元素已从DOM中删除.这里的"神奇"是JavaScript的垃圾收集器.浏览器看到它sourceEl仍然是作用域(在setTimeout闭包内)并且不会将引用的DOM元素遗留在sourceEljQuery对象中.

这里的问题不是JScript(Microsft的Javascript实现)的垃圾收集器,而是JScript在设置元素时如何处理DOM解析innerHTML.

其他浏览器将简单地分离所有childNodes(当没有更多活动引用时将由GC收集它们)并将传递的html字符串解析为DOM元素,并将它们附加到DOM.Jscript,另一方面,也将删除分离的childNodes' innerHTML/ childNodes.检查这个小提琴是为了说明.

事实上,该元素仍然存在于IE中并附加到DOM:

在此输入图像描述

它已经没有childNode了.

如果你打算重新使用元素而不是"覆盖"它,那么为了防止这种行为,.clone()元素(如问题中所述)或.detach()它在调用.html()其父元素之前.

这是在元素被覆盖之前使用的小提琴.detach(),在所有浏览器中都能正常工作.