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 = "&lt;tr&gt;&lt;td&gt;some value&lt;/td&gt;&lt;/tr&gt;"; 有什么问题? -1。如果您愿意解释 jQuery 在内部做什么(以及为什么),我不会投反对票。 推荐一个框架来完成工作并没有错。事实上,重新发明***在我们的业务中也是“不赞成”的,这取决于您需要多少 JavaScript(jQuery 可能会证明对更多任务足够有用)。现在,将&lt;tr&gt; 附加到&lt;body&gt; - 不可原谅的:) @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

哪个更适合实时服务器 wamp 或 xampp?

哪个更适合使用,vector 或 arraylist? [复制]

哪个更适合使用,vector 或 arraylist? [复制]

执行器服务或守护线程哪个更适合多线程?

模式对话框的 iframe 与 innerHTML - 哪个更好?