23

我已经看到了几种不同的方法来向 DOM 添加元素。例如,最普遍的似乎是

document.getElementById('foo').innerHTML ='<p>Here is a brand new paragraph!</p>';

或者

newElement = document.createElement('p');
elementText = document.createTextNode('Here is a brand new parahraph!');
newElement.appendChild(elementText);
document.getElementById('foo').appendChild(newElement);

但我不确定做任何一个的好处。关于什么时候应该完成另一个,或者其中一个完全是错误的,是否有经验法则?

4

6 回答 6

22

一些注意事项:

  • innerHTML在 IE 中使用速度更快,但在 chrome + firefox 中使用速度较慢。这是一个用一组不断变化的s + s 显示这一点的基准这是一个基准,显示了一个恒定的、简单的.<div><p><table>

  • 另一方面,DOM 方法是传统的标准——innerHTML在 HTML5 中被标准化——并且允许您保留对新创建元素的引用,以便以后可以修改它们。

  • 因为 innerHTML 快速(足够)、简洁且易于使用,所以很容易在每种情况下都依赖它。但要注意 using会从文档中innerHTML分离所有现有的 DOM 节点。这是您可以在此页面上测试的示例。

    首先,让我们创建一个函数,让我们测试一个节点是否在页面上:

    function contains(parent, descendant) {
        return Boolean(parent.compareDocumentPosition(descendant) & 16);
    }
    

    true如果parent包含,这将返回descendant。像这样测试它:

    var p = document.getElementById("portalLink")
    console.log(contains(document, p)); // true
    document.body.innerHTML += "<p>It's clobberin' time!</p>";
    console.log(contains(document, p)); // false
    p = document.getElementById("portalLink")
    console.log(contains(document, p)); // true
    

    这将打印:

    true
    false
    true
    

    看起来我们的使用innerHTML应该不会影响我们对portalLink元素的引用,但确实如此。需要再次检索才能正确使用。

于 2011-12-11T04:02:13.660 回答
5

有许多不同之处:

  1. innerHTML仅由 W3C 为 HTML 5 标准化;尽管一段时间以来它已经成为所有流行浏览器的事实上的标准,但从技术上讲,在 HTML 4 中,它是一个供应商扩展,遵循标准的开发人员永远不会被抓死使用。另一方面,它更方便,实际上它被所有浏览器支持。
  2. innerHTML 替换元素的当前内容(它不允许你修改它)。但同样,如果您不介意此限制,您将获得便利。
  3. innerHTML 已被测量为更快(诚然,该测试涉及今天未广泛使用的旧版本浏览器)。
  4. innerHTML如果将其设置为用户提供的未正确编码的值(例如 ),则可能表示安全风险 (XSS el.innerHTML = '<script>...')。

基于以上,似乎一个实际的结论可能是:

  • 如果您不介意innerHTML有点限制的事实(仅完全替换以目标元素为根的 DOM 子树)并且您不会通过注入用户提供的内容来冒漏洞的风险,请使用它。否则,请使用 DOM。
于 2011-12-11T04:00:47.750 回答
1

根据此基准数据,您将获得innerHTML比创建 DOM 元素更快的结果。使用较旧的 IE 版本时尤其明显。

于 2011-12-11T04:00:49.510 回答
1

虽然这是一个旧线程,但没有提到的一件事是 whileinnerHTML可以更快,应该小心。UsinginnerHTML将渲染被修改元素的每个子元素,无论新旧。因此,一个单一innerHTML的分配比 DOM 创建/附加更快(稍微),但多个innerHTML肯定会更慢。

例如:

for(let i=0; i < 10; i++)
   document.body.innerHTML+='<div>some text</div>';

将慢近 5 倍

let html = '';
for(let i=0; i < 10; i++)
   html += '<div>some text</div>';

document.body.innerHTML = html;

由于innerHTML赋值是让浏览器本机创建/附加元素,第二种方法导致 10 个元素被本机创建/附加,而第一种方法导致 55 个元素被创建/附加(并且 45 个被销毁):在第一个循环中创建了 1 个元素-迭代,在第二次循环迭代中创建 2 个元素(原始被销毁),在第三次循环迭代中创建 3 个元素(前 2 个被销毁),依此类推。

如果您使用innerHTML速度,则必须确保在进行innerHTML分配之前首先创建整个 html 字符串,例如创建新的 DOM 容器/元素。 innerHTML另一方面,在附加任何具有现有子节点的容器时,尤其是那些具有大量子节点的容器时,会降低性能。

于 2019-03-22T19:49:15.167 回答
0

我总是更喜欢可读性,除非性能差异很大。在这种一次性的情况下,这可能是一个边际差异。

在这样的一次性情况下,设置innerHTML属性将是最容易阅读的。

但是,如果您在 JavaScript 中进行大量程序化内容生成,那么 DOM 选项会更简洁、更容易阅读和理解。

例子:

比较这段innerHTML代码:

http://jsfiddle.net/P8m3K/1/

// Takes input of a value between 1 and 26, inclusive,
// and converts it to the appropriate character
function alphaToChar(alpha)
{
    return String.fromCharCode('a'.charCodeAt() + alpha - 1);
}

var content = "<ul>";
for(i = 0; i < 10; ++i)
{
    content += "<li>";
    for(j = 1; j <= 26; ++j)
    {
        content += "<a href=\"" + alphaToChar(j) + ".html\">"
            + alphaToChar(j)
            + "</a>";
    }
    content += "</li>";
}
document.getElementById("foo").innerHTML = content;

到这个 DOM 代码:

http://jsfiddle.net/q6GB8/1/

// Takes input of a value between 1 and 26, inclusive,
// and converts it to the appropriate character
function alphaToChar(alpha)
{
    return String.fromCharCode('a'.charCodeAt() + alpha - 1);
}

var list = document.createElement("ul");
for(i = 0; i < 10; ++i)
{
    var item = document.createElement("li");
    for(j = 1; j <= 26; ++j)
    {
        var link = document.createElement("a");
        link.setAttribute("href", alphaToChar(j) + ".html");
        link.innerText = alphaToChar(j);
        item.appendChild(link);
    }
    list.appendChild(item);
}
document.getElementById("foo").appendChild(list);

在这个级别,他们开始变得非常相似的长度明智。

但是 DOM 代码将更容易维护,并且您不太可能犯难以诊断的拼写错误或错误,例如省略结束标记。您的元素将在您的文档中,或者它们不会。

  • 对于更复杂的场景(例如构建树状菜单),您可能会先使用 DOM 代码。
  • 在您必须将多种类型的内容附加在一起以构建具有更多异构内容的文档的情况下,它变成了灌篮。您不必确保在调用父附加代码之前调用您的子附加代码。
  • 对于添加、删除或修改现有静态内容的场景,DOM 通常会胜出。

如果您开始进行复杂的 DOM 修改(我提到的最后一件事),您肯定会想要查看一个围绕 DOM 修改构建的库,例如 jQuery

于 2011-12-11T05:39:21.177 回答
0

第一个是直截了当的,更容易阅读,更少的代码并且可能更快。
第二个让你对你创建的元素有更多的控制,也就是说,使用 JS 修改新元素变得更加容易(比如附加事件,或者,只是在你的代码中使用它)。
第二种方式适用于喜欢“干净”代码(没有快速和肮脏)的“纯粹主义者”。
我说,两者都用,看看哪种更适合你,然后就用它。

于 2011-12-11T04:00:27.513 回答