除了安全性之外,使用 createElement 而不是修改 innerHTML(而不是仅仅丢弃已经存在的内容并替换它)还有几个优点,就像 Pekka 已经提到的那样:
在附加元素时保留对 DOM 元素的现有引用
当您附加到(或以其他方式修改)innerHTML 时,该元素内的所有 DOM 节点都必须重新解析和重新创建。如果您保存了对节点的任何引用,它们将基本上是无用的,因为它们不再显示了。
保留附加到任何 DOM 元素的事件处理程序
这实际上只是最后一种情况的特例(尽管很常见)。设置 innerHTML 不会自动将事件处理程序重新附加到它创建的新元素,因此您必须自己跟踪它们并手动添加它们。在某些情况下,事件委托可以消除这个问题。
在某些情况下可能更简单/更快
如果您要进行大量添加,您肯定不想一直重置 innerHTML,因为虽然简单更改更快,但重复重新解析和创建元素会更慢。解决这个问题的方法是在一个字符串中构建 HTML,并在完成后设置一次 innerHTML。根据具体情况,字符串操作可能比创建元素并附加它们要慢。
此外,字符串操作代码可能更复杂(特别是如果您希望它是安全的)。
这是我有时使用的一个函数,它使 createElement 的使用更加方便。
function isArray(a) {
return Object.prototype.toString.call(a) === "[object Array]";
}
function make(desc) {
if (!isArray(desc)) {
return make.call(this, Array.prototype.slice.call(arguments));
}
var name = desc[0];
var attributes = desc[1];
var el = document.createElement(name);
var start = 1;
if (typeof attributes === "object" && attributes !== null && !isArray(attributes)) {
for (var attr in attributes) {
el[attr] = attributes[attr];
}
start = 2;
}
for (var i = start; i < desc.length; i++) {
if (isArray(desc[i])) {
el.appendChild(make(desc[i]));
}
else {
el.appendChild(document.createTextNode(desc[i]));
}
}
return el;
}
如果你这样称呼它:
make(["p", "Here is a ", ["a", { href:"http://www.google.com/" }, "link"], "."]);
你会得到这个 HTML 的等价物:
<p>Here is a <a href="http://www.google.com/">link</a>.</p>
@Matthew Crumley的答案