DOM API 或 innerHTML 哪个更适合 DOM 操作?
Posted
技术标签:
【中文标题】DOM API 或 innerHTML 哪个更适合 DOM 操作?【英文标题】:What is better for DOM manipulation - the DOM API or innerHTML? 【发布时间】:2011-03-27 16:05:45 【问题描述】:我有以下代码:
tr = document.createElement("tr");
root.appendChild(tr);
td = document.createElement("td");
td.appendChild(document.createTextNode("some value"));
tr.appendChild(td);
嗯,这段代码和
root.innerhtml = "<tr><td>some value</td></tr>";
第一个版本可能是更好的选择,因为浏览器不必渲染字符串。但它太长了。特别是对于更大的结构,这种实现变得非常难以阅读。所以我觉得有更好的方法来写这个(没有任何 javascript 库)。你将如何实现它以使代码更具可读性? (现在我正在用 cmets 分离代码。)
【问题讨论】:
其实innerHTML比创建DOM节点要快得多。见quirksmode.org/dom/innerhtml.html。 @KennyTM:那些测试结果是两年前的。 @Gumbo:对于今天的 Gecko (Firefox) 和 Presto (Opera),innerHTML 仍然是最快的,但对于 WebKit (Chrome & Safari),“表格方法”更快。对于所有这 4 个浏览器来说,像 OP 那样创建 DOM 节点是最慢的。 @Gumbo:过去两年有大量浏览器没有升级。 @KennyTM:我想这取决于测试环境。因为我的测试还有其他结果。如果我平均测试的浏览器(Chrome、Firefox、Opera、Safari)的平均值,我会得到以下结果:W3C DOM 1 27.5 ms,W3C DOM 2 28.25 ms,表格方法 27.75 ms,innerHTML 1 30 ms,innerHTML 2 30女士。 【参考方案1】:您总是可以围绕笨重的 DOM API 编写包装函数,以使代码更具可读性。我通常使用类似的东西:
function newElement (type,attr,children)
var el = document.createElement(type);
for (var n in attr)
if (n == 'style')
setStyle(el,attr[n]); /* implementation of this function
* left as exercise for the reader
*/
else
el[n] = attr[n];
if (children)
for (var i=0; i<children.length; i++)
el.appendChild(children[i]);
function newText (text)
document.createTextNode(text);
然后你可以编写更多的声明性代码:
var tr = newElement('tr',,[
newElement('td',,[
newText('some value')
])
]);
只要记住 css 和 javascript 之间的区别:
var div = newElement('div',
className:'foo',
style:
marginLeft:'10px'
,[
newText('notice we use "className" instead of class" '+
'and "marginLeft" instead of "margin-left"')
]);
【讨论】:
【参考方案2】:innerHTML
比 DOM 快 definitely(参见讨论部分)。前段时间,我遇到了一种用innerHTML
方便地编写大型HTML结构的方法,字符串连接要好一些,或者必须编写大型结构:
var html = [
'<ul class="myclass">',
'<li class="item">item1</li>',
'<li class="item">item2</li>',
'<li class="item">item3</li>',
'<li class="item">item4</li>',
'<li class="item">item5</li>',
'</ul>'
].join("");
root.innerHTML =html;
【讨论】:
需要设置属性;innerHTML
是 not a method。
@alex 非常感谢,这是一个错字:D【参考方案3】:
正如我在评论中提到的,innerHTML 实际上比创建 DOM 节点更快,但它是非结构化的。
一种比创建 DOM 节点更快但仍然结构化的方法是使用the DOM 2 table methods:
var tr = root.insertRow(-1);
var td = tr.insertCell(0);
var txt = document.createTextNode("some value");
td.appendChild(txt);
// or simply: td.innerHTML = "some value";
【讨论】:
【参考方案4】:嘿,我在这个游戏上迟到了,但想为大家添加这个信息。 在一些移动浏览器开发过程中,我遇到了这个问题,并且想亲眼看看这些天哪个更好。
在我的 android 手机上,这里有一些有趣的结果:
DOM:614 / 25 内部HTML:697 / 542 DOM:546 / 18 内部HTML:639 / 552 DOM:604 / 12 内部HTML:641 / 534 DOM:619 / 11 内部HTML:643 / 554 DOM:618 / 13 内部HTML:655 / 600第一个数字是添加 2700 个li
元素的实际执行情况。
而且,更有趣是第二个数字,即ol
使用innerHTML = '';
清除这些结果需要多长时间
亲自尝试DOM vs innerHTML。
【讨论】:
【参考方案5】:innerHTML
最初是 IE 的东西,我相信。
我也认为你设置了它,因为它不是一种方法,所以第二个例子是
root.innerHTML = "<tr><td>some value</td></tr>";
但要回答你的问题,innerHTML
更方便,但也常说速度较慢。但是,KennyTM 在 cmets 中说它是 much faster。
您必须决定是否值得以 DOM API 方式或 innerHTML
方式进行性能折衷(可能可以忽略不计)。
【讨论】:
【参考方案6】:我会重新排序以使其更具可读性
var d = document;
td = d.createElement("td");
tr = d.createElement("tr");
td.appendChild( d.createTextNode("some value") );
tr.appendChild(td);
root.appendChild(tr);
【讨论】:
【参考方案7】:使用 jQuery http://jquery.com/
$('#root tbody').append('<td><td>some value</td></td>');
它甚至会使用正确的 DOM 方法。
编辑:来自 jQuery 文档:
jQuery 是一个快速而简洁的 简化的 JavaScript 库 HTML文档遍历,事件 处理、动画和 Ajax 快速网络交互 发展。 jQuery 旨在 改变你写作的方式 JavaScript。
** 编辑:** 另外,我使上面的示例更加符合 HTML 标准 @koby ;)
【讨论】:
“使用 jQuery” 对未标记 jQuery 的 JavaScript 的问题通常不赞成。但是,我没有反对...阅读Bobince's enjoyable article :) @June R 是否值得包含一个 24kB 的库来保存少量字符?root.innerHTML = "<tr><td>some value</td></tr>";
有什么问题?
-1。如果您愿意解释 jQuery 在内部做什么(以及为什么),我不会投反对票。
推荐一个框架来完成工作并没有错。事实上,重新发明***在我们的业务中也是“不赞成”的,这取决于您需要多少 JavaScript(jQuery 可能会证明对更多任务足够有用)。现在,将<tr>
附加到<body>
- 不可原谅的:)
@June R 当然它可以做更多,但是 OP 什么时候说他需要做更多?此外,我不会说现在是从原生 JavaScript 继续前进的时候了。库有它们的位置(我在 95% 的项目中使用它们),但了解原生 JavaScript 是一项宝贵的技能。你永远不能太依赖图书馆(我从经验中知道这一点)。这让我很恼火,我现在需要使用短语 native JavaScript。【参考方案8】:
您是否尝试过使用 JavaScript 模板引擎?
它们通常通过innerHTML
注入 HTML 字符串,并且在桌面和移动设备中都比 DOM 操作快得多,同时保持视图和逻辑之间的分离。
我们使用PURE,它完全分离了 HTML 标记和 JavaScript 逻辑。设计人员和开发人员可以在相同的资源上一起工作。
如果您不喜欢它,您可以在网络上找到许多更适合您口味的其他产品。
【讨论】:
不幸的是我不能使用这个我自己写一个工具。所以我真的不知道我会有什么样的结果结构。而且由于我的应用程序是一个实用程序,我不想在我的代码中添加任何依赖项。我决定使用纯js。但是模板引擎看起来很有前途,我可以在设置页面中使用它们。谢谢你的建议 在小样本上测量原始速度非常困难。很多参数使它变得困难(当你测量时,javascript 正在运行,浏览器版本和怪癖,取决于内容的类型,......)。我们使用 DOM 开始我们的 Web 应用程序,因为它更优雅,但是当页面开始拥挤时,对于生产环境来说太慢了,我们使用了模板引擎。我认为 innerHTML 注入与浏览器从 Web 服务器接收 HTML 的逻辑并没有太大的不同。【参考方案9】:我自己编写了一些测试来比较 innerHTML 和 DOM API。 DOM API 肯定更快。
这是结果(我在 Firefix 3.6.8 和 Chrome 5.0.375.125 beta 上测试过): http://yilmazhuseyindevelopment.appspot.com/ois/images/ahh5aWxtYXpodXNleWluZGV2ZWxvcG1lbnRyEQsSCUltYWdlRGF0YRiptwUM
在第一次测试中,我使用 DOM API 和 innerHTML 在页面正文中添加了一个文本节点 1000 次。
在第二个测试中,我使用 DOM API 和内部 HTML 创建了一个表。这是我的测试的实际代码:
<html>
<head>
<script type="text/javascript">
window.onload = function()
var body = document.getElementsByTagName("body")[0];
var text,table,tr,td;
var count = 1000;
console.time("DOM");
for(var i = 0 ; i<count ; i++)
text = document.createTextNode("text");
body.appendChild(text);
body.removeChild(text)
console.timeEnd("DOM");
console.time("innerHTML");
for(var i = 0 ; i<count ; i++)
body.innerHTML = "text";
body.innerHTML = "";
console.timeEnd("innerHTML");
//table structure
console.time("DOM2");
for(var i = 0 ; i<count ; i++)
table = document.createElement("table");
tr = document.createElement("tr");
td = document.createElement("td");
text = document.createTextNode("text");
table.appendChild(tr);
tr.appendChild(td);
td.appendChild(text);
body.appendChild(table);
body.removeChild(table);
console.timeEnd("DOM2");
console.time("innerHTML2");
for(var i = 0 ; i<count ; i++)
body.innerHTML = "<table><tr><td>text</td></tr></table>";
body.innerHTML = "";
console.timeEnd("innerHTML2");
</script>
</head>
<body/>
</html>
我猜这意味着 DOM API 对于现代浏览器来说更好(性能方面)。
【讨论】:
以上是关于DOM API 或 innerHTML 哪个更适合 DOM 操作?的主要内容,如果未能解决你的问题,请参考以下文章
哪个更适合用于序列化对象? JsonSerializer 或 JsonConvert
哪个更适合使用,vector 或 arraylist? [复制]