我已经看到了一些向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);
但是我不确定做任何一个的好处。是否有一个经验法则是关于何时应该完成另一个,或者其中一个是否完全错了?
答案 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)
有许多不同之处:
innerHTML
仅由W3C标准化为HTML 5;虽然它已经成为所有流行浏览器的事实上的标准,但在HTML 4中技术上它是一个供应商扩展,标准坚持的开发人员永远不会被抓住使用。另一方面,所有浏览器都支持它更加方便和实用。innerHTML
替换元素的当前内容(它不允许您修改它)。但同样,如果你不介意这个限制,你会获得便利。innerHTML
has been measured要快得多(诚然,该测试涉及目前尚未广泛使用的旧版浏览器)。innerHTML
设置为未正确编码的用户提供的值(例如el.innerHTML = '<script>...'
),则innerHTML
可能代表安全风险(XSS)。基于以上所述,似乎一个实际的结论可能是:
答案 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
代码:
// 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代码:
// 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修改构建的库like jQuery。