简体   繁体   English

设置innerHTML属性会中断对子元素的引用

[英]setting innerHTML property breaks references to child elements

The issue is similar to the one described here , as far as I can tell. 据我所知,这个问题类似于此处描述的问题。 However, I am not using mootools and my question and results are different. 但是,我没有使用mootools,因此我的问题和结果不同。 This is a test page to demonstrate the issue: http://jsfiddle.net/S7rtU/2/ . 这是一个演示该问题的测试页: http : //jsfiddle.net/S7rtU/2/

I add elements to a container using createElement and appendChild . 我使用createElementappendChild将元素添加到容器中。 As I add each, I also store a reference to it in a private array ( elems ). 在添加每个elems ,我还将对它的引用存储在私有数组( elems )中。

Then, I decide to clear the container, and do so by setting container.innerHTML = '' . 然后,我决定清除容器,并通过设置container.innerHTML = ''来清除容器。

(In my example, I set it first to a pending message, and then 3s later, using setTimeout , I clear it. This is to give time to observe the changes to the DOM.) (在我的示例中,我首先将其设置为待处理的消息,然后在3秒钟后使用setTimeout其清除。这是为了给时间观察DOM的更改。)

Then, I try to repopulate the container from the elems array, calling container.appendChild for each of the stored elements. 然后,我尝试从elems数组重新填充容器,为每个存储的元素调用container.appendChild

I have tested on the browsers I have at hand: Firefox 17.0.1, Chrome 23.0.1271.97, Safari 3.1.2, IE 6 and IE 7. All except IE 6 & 7 will actually restore those elements . 我已经在以下浏览器上进行了测试:Firefox 17.0.1,Chrome 23.0.1271.97,Safari 3.1.2,IE 6和IE7。除IE 6和7以外的所有其他浏览器实际上都会还原这些元素 So they are successfully stored in memory and references not destroyed. 因此它们已成功存储在内存中,并且引用未销毁。 Furthermore, the event handlers registered to those elements still work. 此外,注册到那些元素的事件处理程序仍然有效。

In IE, the elements do not reappear. 在IE中,元素不会重新出现。

What I have read about this issue, including the other SO question, seem to suggest that references are supposed to be broken when you modify innerHTML on the container. 我所读到的有关此问题的内容,包括另一个SO问题,似乎表明您在修改容器上的innerHTML时应该破坏了引用。 Event handlers are also supposed to be broken. 事件处理程序也应该被破坏。 However the 3 modern browsers I tested do not break the references, nor the event handlers. 但是,我测试的3种现代浏览器都不会破坏引用,也不会破坏事件处理程序。

Of course, to make this work in IE I can use something like this, but this is significant extra processing if there are lots of elements: 当然,要使此功能在IE中起作用,我可以使用类似这样的方法,但是如果有很多元素,这将是大量的额外处理:

function explicitClearContainer() {
    var e;
    // Explicitly remove all elements
    for (var i = 0; i < elems.length; ++i) {
        e = elems[i];
        // Update the reference to the removed Node
        elems[i] = e.parentNode.removeChild(e);
    }
}

My question is what is known about this behaviour, what can be expected in different environments, what are the pitfalls of using this sort of technique? 我的问题是对这种行为的了解是什么,在不同的环境中可以期待什么,使用这种技术的陷阱是什么?

I would appreciate any comments. 我将不胜感激。

The innerHTML property was only "standardised" in HTML5, which really just documents common browser behaviour for many features. innerHTML属性仅在HTML5中“标准化”,实际上只是记录了许多功能的常见浏览器行为。 Things such as innerHTML have been implemented differently in different browsers and will continue to be different for some time, so best to avoid using it if it's causing problems. 诸如innerHTML之类的东西在不同的浏览器中实现的方式有所不同,并且在一段时间内仍将有所不同,因此,如果它引起问题,则最好避免使用它。

There are other approaches to clearing the child nodes of an element, eg: 还有其他清除元素子节点的方法,例如:

function removeContent(element) {
  while (element.firstChild) {
    element.removeChild(element.firstChild);
  }
}

Which should avoid your issues with innerHTML and is a bit less code than your version. 这应该避免您的innerHTML问题,并且代码比您的版本少。 You can also replace element with a shallow clone of itself, but that may cause other issues. 您也可以将其element替换为其自身的浅表克隆,但这可能会导致其他问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM