什么是更好的,通过DOM函数追加新元素,或附加HTML标签的字符串?

时间:2011-12-11 03:55:52

标签: javascript dom appendchild

我已经看到了一些向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);

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

6 个答案:

答案 0 :(得分:19)

一些注意事项:

  • 在IE中使用innerHTML更快,但在chrome + firefox中使用速度更慢。 Here's one benchmark使用不断变化的<div> s + <p> s来表示这一点; here's a benchmark为常量,简单<table>显示此内容。

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

  • 因为innerHTML快速(足够),简洁且易于使用,所以在任何情况下都倾向于使用它。但要注意使用 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元素的引用,但确实如此。需要再次检索才能正常使用。

答案 1 :(得分:5)

有许多不同之处:

  1. innerHTML仅由W3C标准化为HTML 5;虽然它已经成为所有流行浏览器的事实上的标准,但在HTML 4中技术上它是一个供应商扩展,标准坚持的开发人员永远不会被抓住使用。另一方面,所有浏览器都支持它更加方便和实用。
  2. innerHTML 替换元素的当前内容(它不允许您修改它)。但同样,如果你不介意这个限制,你会获得便利。
  3. innerHTML has been measured要快得多(诚然,该测试涉及目前尚未广泛使用的旧版浏览器)。
  4. 如果
  5. innerHTML设置为未正确编码的用户提供的值(例如el.innerHTML = '<script>...'),则
  6. innerHTML可能代表安全风险(XSS)。
  7. 基于以上所述,似乎一个实际的结论可能是:

    • 如果您不介意{{1}}有点限制(仅根据目标元素完全替换DOM子树),并且您不会通过注入用户提供的内容来冒漏洞,用那个。否则,请使用DOM。

答案 2 :(得分:1)

根据this benchmark data,与使用innerHTML相比,您将获得比创建DOM元素更快的结果。使用旧的IE版本时尤为明显。

答案 3 :(得分:1)

尽管这是一个旧线程,但innerHTML可以更快,但没有提到的一件事是,请务必小心。使用innerHTML会渲染修改后的元素的每个子元素,无论新旧。这样,一个单独的innerHTML分配(比)DOM创建/附加要快(略),但是多个innerHTML肯定会更慢。

例如:

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

慢将近五倍

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在将任何容器与现有childNode(尤其是具有大量childNode的容器)附加到容器时会导致性能下降。

答案 4 :(得分:0)

第一个是直接的,更容易阅读,更少的代码,可能更快 第二个可以让您更好地控制您创建的元素,即使用JS修改新元素更容易(比如附加事件,或者只是在代码中使用它)。
第二种方式是“纯粹主义者”喜欢“干净”的代码(没有快速和肮脏) 我说,同时使用两者,看看哪种更适合你,然后继续使用它。

答案 5 :(得分: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代码将更容易维护,并且您更难以制作难以诊断的拼写错误或错误,例如省略结束标记。您的元素将在您的文档中,或者它们不会。

  • 对于更复杂的场景(比如构建treed菜单),你可能会提前使用DOM代码。
  • 在必须将多种类型的内容附加在一起以构建具有更多异构内容的文档的场景中,它变成了一个扣篮。在调用父附加代码之前,您无需确保调用子附加代码。
  • 在添加,删除或修改现有静态内容的场景中,DOM通常会获胜。

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