添加DOM元素,什么是正确的方法?

18

这个问题可能很蠢,或者很基础。

有人可以解释一下在添加DOM元素时哪种方法最好吗?我们有两种添加DOM元素的方式。

场景:需要在现有的<div id="theEl"></div>内部添加<strong>Hi</strong>

  1. 通过编辑其中的HTML。

     document.getElementById("theEl").innerHTML = '<strong>Hi</strong>';
    
  2. 通过使用document.createElement()方法。

  3.  var hi = document.createTextNode("Hi"),
     strong = document.createElement("strong");
     strong.appendChild(hi);
     mydiv = document.getElementById("theEl");
     document.body.insertBefore(strong, mydiv);
    

问题

  1. 最好的方式是什么?一个是单行,另一个是大约五行。
  2. 性能方面怎么样?
  3. 正确的方式或最佳实践是什么?
  4. 代码整体上有区别吗?

如果这个问题看起来没有意义,请让我知道,我很乐意关闭甚至删除这个问题。谢谢。


对于那些想要关闭问题的人,请注意,这个问题不是那个问题的重复。我刚刚注意到的一件事是,使用createElement()可以保留附加到元素的事件处理程序。尽管这是一个很好的观点,但任何基本网页中都有jQuery,它提供了代理和其他允许我在HTML更改后仍将事件附加到元素的功能。


2
我更喜欢方法1来进行简单的HTML插入。但是如果我必须使用循环生成一些节点,那么方法2可能更容易。 - Raptor
2
https://dev59.com/xXA85IYBdhLWcg3wF_cO - KingKongFrog
1
为了提高性能,innerHTML 要快得多。http://www.quirksmode.org/dom/innerhtml.html - Andreas Wong
@Brad 你怎么样才能插入一个 JavaScript 包含器 (<script src=""></script>) 并使其被包含和运行,而不创建元素。因为在这种情况下,它需要被初始化才能被包含。你明白我的意思吗? - Praveen Kumar Purushothaman
1
无论如何,这里有多个方面需要考虑,这就是为什么我认为它不够建设性的原因;没有冒犯之意……只是我认为问题应该更加具体。 - Ja͢ck
显示剩余23条评论
4个回答

9

并没有所谓的“最佳”或“最佳实践”。它们是两种不同的添加内容的方法,具有不同的特点。选择哪种方式取决于您的特定情况。

对于创建大量元素,一次性设置一个HTML块通常比创建和插入大量单独元素要快。但是,如果您真的关心这方面的性能,您需要在类似jsperf的工具中测试您的特定情况。

对于具有很好控制力的元素(例如从变量设置类、从变量设置内容等),通过createElement()更容易完成,因为您可以直接访问每个元素的属性,而无需构造字符串。

如果您真的不知道两种方法之间的区别,并且在特定情况下看不到使用其中一种方法的明显原因,则使用更简单、代码更少的那一种。这就是我做的。

回答您的具体问题:

  1. 并没有“最佳”方法。选择最适合您情况的方法。
  2. 您将需要测试您特定情况的性能。在某些情况下,通过设置一个大字符串来设置所有对象的.innerHTML比逐个创建和插入对象更快。
  3. 并没有“正确的方法”或“最佳实践”。参见答案#1。
  4. 如果它们被编码为创建相同的最终结果,则两种方法在最终创建的结果上没有区别。

通常,通过了解浏览器和JavaScript的行为,我们不能猜测哪个性能更好吗?正如你所说,拥有代码块是更糟糕的,我也同意。 - Praveen Kumar Purushothaman
2
@PraveenKumar - 当一个人关心优化性能时,猜测从来都不是一个好主意。你必须进行测量才能知道。我认为答案是“这取决于情况,可能也取决于浏览器”。 - jfriend00
是的,我有点同意你的看法... :) - Praveen Kumar Purushothaman

5

我实际上喜欢两种方法的结合: 使用createElement创建外部元素,以保留事件处理程序,然后使用innerHTML为该元素的内容添加方便和提高性能。例如:

var strong = document.createElement('strong');
strong.innerHTML = 'Hi';
document.getElementById('theEl').appendChild(strong);

当你添加的内容比较复杂时,这种技术会更加有用;然后你可以通常使用innerHTML (除了外部元素之外),但是你不需要移除任何事件监听器。

哈哈...这有点新鲜和不错... :) - Praveen Kumar Purushothaman

1
"我应该如何理解“最好”?如果只进行一次DOM操作,那么一切都很好,并且表现出相同的性能。但是当您需要插入多个DOM时,情况就会有所不同。
背景:
每次插入DOM节点时,浏览器都会呈现页面的新图像。因此,如果您在DOM节点内插入多个子级,则浏览器将多次呈现它。这是您将看到的最慢的操作。
解决方案:
因此,我们需要一次性添加大多数子元素。使用一个空的DOM节点。内置的是createDocumentFragment();"
var holder = createDocumentFragment();
// append everything in the holder
// append holder to the main dom tree

真正的答案

如果情况如您所描述,我更喜欢最短的解决方案。因为一个DOM操作不会有性能惩罚。


1

1. 最好的方法是什么?一个是单行,另一个是大约五行。

这取决于上下文。作为经验法则,你可能想要适度使用 innerHTML

2. 性能方面如何?

DOM 操作明显优于 innerHTML,但浏览器似乎在不断改进 innerHTML 的性能。

3. 正确的方式或最佳实践是什么?

参见 #1。

4. 整个代码之间有什么区别吗?

有。innerHTML 示例将替换现有元素的内容,而 DOM 示例将把新元素放在旧元素旁边。你可能想写 mydiv.appendChild(strong),但这仍然不同。现有元素的子节点被附加而不是被替换。


1
我记得大约一年前看过那些测试,认为它们非常有偏见,于是写了自己的测试,并得到了我预期的结果。我想这一切都在SO上有记录。 - Dagg Nabbit
能够得到那个链接会很不错。 :) - Praveen Kumar Purushothaman
1
@PraveenKumar,找不到了,但看看这个:http://jsperf.com/w3c-dom-vs-innerhtml/10--请注意,DOM测试的性能优于innerHTML测试,除了“fastInnerHTML”测试之外,它非常快,但这并不是innerHTML的正常使用方式,也可能不是PPK所想要的。 - Dagg Nabbit
1
@PraveenKumar,我认为这些测试过于复杂,不代表实际情况。如果我没记错的话,PPK的表格测试在插入一些从单元格到单元格变化的虚拟数据而不仅仅是插入星号时会产生非常不同的结果。这是我之前做的一个简单测试:http://jsperf.com/innerhtml-v-dom - Dagg Nabbit
我认为性能并不是innerHTML的真正问题,除非你在谈论像foo.innerHTML += bar这样的糟糕情况。如果你有一些标记文本或类似的东西,innerHTML就可以了。如果你要做更复杂的事情,使用DOM可能会更清晰、更少出错。 - Dagg Nabbit
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接