Javascript jquery:最快的DOM插入?
对于如何插入大量HTML,我有一种不好的感觉。 假设我们得到:Javascript jquery:最快的DOM插入?,javascript,jquery,dom,Javascript,Jquery,Dom,对于如何插入大量HTML,我有一种不好的感觉。 假设我们得到: var html=“…” 我想把这个放进 $(“#mydiv”) 以前我做过类似的事情 var html_obj=$(html) $(“#mydiv”).append(html#obj) jQuery解析html以创建DOM对象是否正确?这就是我在某处读到的(更新:我的意思是我读过,jQuery解析html以手动创建整个DOM树-这是胡说八道吧?!),所以我更改了代码: $(“#mydiv”).attr(“innerHTML”,$(
var html=“…”
我想把这个放进
$(“#mydiv”)
以前我做过类似的事情
var html_obj=$(html)代码>
$(“#mydiv”).append(html#obj)代码>
jQuery解析html
以创建DOM对象是否正确?这就是我在某处读到的(更新:我的意思是我读过,jQuery解析html以手动创建整个DOM树-这是胡说八道吧?!),所以我更改了代码:
$(“#mydiv”).attr(“innerHTML”,$(“#mydiv”).attr(“innerHTML”)+html)代码>
感觉更快,是吗?这是否等于:
document.getElementById(“mydiv”).innerHTML+=html
?或者jquery在后台做一些额外的昂贵的事情
我也很想学习其他方法。对于初学者,编写一个脚本,将每种方法执行100次或1000次所需的时间乘以
为了确保重复不会以某种方式被优化——我不是JavaScript引擎专家——每次插入的html都会有所不同,比如将“0001”然后“0002”然后“0003”放在表的某个单元格中。您试图避免什么?“坏感觉”是非常模糊的。如果您听过“DOM很慢”,并决定“避免DOM”,那么这是不可能的。将代码插入页面的每一种方法,包括innerHTML,都会导致创建DOM对象。DOM是浏览器内存中文档的表示形式。您希望创建DOM对象
人们之所以说“DOM很慢”,是因为使用document.createElement()
创建元素比在某些浏览器中使用非标准的innerHTML属性要慢,后者是用于创建元素的官方DOM接口。这并不意味着创建DOM对象是不好的,有必要创建DOM对象,否则您的代码将一事无成。您提到对替代方案感兴趣。如果您查看的列表中,您会发现一些专用于以编程方式生成DOM树的方法。例如,见或;但是还有其他的方法。innerHTML速度非常快,在很多情况下,只要设置它,您就会得到最好的结果(我只需要使用append)
但是,如果“mydiv”中已经有很多内容,那么您将强制浏览器再次解析和呈现所有内容(之前的所有内容,以及所有新内容)。您可以通过在“mydiv”中添加文档片段来避免这种情况:
这样,只有您的新内容被解析(不可避免),而现有内容不会被解析
编辑:我的坏。。。我发现innerHTML在文档片段上不受很好的支持。可以对任何节点类型使用相同的技术。对于您的示例,您可以创建根表节点并将innerHTML插入其中:
var frag = document.createElement('table');
frag.innerHTML = tableInnerHtml;
$("#mydiv").append(frag);
关于使用DOM片段的答案是正确的。如果您有一堆不断插入DOM的html对象,那么您将看到使用该片段可以提高速度。John Resig的这篇文章很好地解释了这一点:
尝试以下操作:
$("#mydiv").append(html);
其他答案,包括已接受的答案,都是慢2-10x:
接受的答案在IE 6、7和8中不起作用,因为您无法设置
元素的innerHTML
,因为IE中有一个bug:。这是附加项的最快方法
附加到DOM树的最快方法是将所有附加缓冲到单个DOM片段中,然后将DOM片段附加到DOM中
这是我在游戏引擎中使用的方法
//Returns a new Buffer object
function Buffer() {
//the framgment
var domFragment = document.createDocumentFragment();
//Adds a node to the dom fragment
function add(node) {
domFragment.appendChild(node);
}
//Flushes the buffer to a node
function flush(targetNode) {
//if the target node is not given then use the body
var targetNode = targetNode || document.body;
//append the domFragment to the target
targetNode.appendChild(domFragment);
}
//return the buffer
return {
"add": add,
"flush": flush
}
}
//to make a buffer do this
var buffer = Buffer();
//to add elements to the buffer do the following
buffer.add(someNode1);
//continue to add elements to the buffer
buffer.add(someNode2);
buffer.add(someNode3);
buffer.add(someNode4);
buffer.add(someN...);
//when you are done adding nodes flush the nodes to the containing div in the dom
buffer.flush(myContainerNode);
在Firefox4中,使用这个对象,我可以每秒向屏幕渲染约1000个项目约40次
这是一个用例。我用创建了一个巨大的字符串,然后用jquery追加这个字符串。
对我来说,它工作得又快又好。这对我来说很有效,但我必须使用append(),而不是appendChild()。输入错误,或者方法名称是否已更改?我不确定这可能是如何忽略的,但我不认为这是一个重命名的方法。我将更新我的帖子。appendChild()是w3c DOM方法,它与jQuery中的append()功能相同(大约)appendChild
仅适用于附加节点;不是HTML字符串或对象。不会$(“#mydiv”)。追加(“+tableInnerHtml+”)代码>是否也这样做?使用document.createElement()
有什么好处?他没有提到他想将一个片段放到多个元素中。他的问题表明他想将一个html框架放入一个元素中。此外,documentfragment
是在jQuery内部隐式创建的。+1,将html构建为字符串,并使用单个“append”而不是使用jQuery构建每个元素,在我的例子中,性能提高了一个数量级(创建280个div,每个div带有一个表和几行,耗时12秒,现在降到1.1)。虽然你可能想减少侮辱……;)+如果你发布了一个jsperf.com链接,那么你的测试是不诚实的。它为每个元素创建一个新的dom片段。假设将所有元素附加到一个dom片段中,然后将其插入dom树中。这是一个真正的测试@Robert:我们不要求技术准确性。@galambalazs,我在您的jsperf中添加了一个新的测试用例。它手动构建dom,这是附加html字符串的唯一真正替代方法。解析显然是一个瓶颈,虽然最初的问题可能没有找到这个瓶颈,但我认为还有其他人希望知道,如果您愿意手动构建它,它的速度会快多少。(它确实回答了标题问题)这些将使用
//Returns a new Buffer object
function Buffer() {
//the framgment
var domFragment = document.createDocumentFragment();
//Adds a node to the dom fragment
function add(node) {
domFragment.appendChild(node);
}
//Flushes the buffer to a node
function flush(targetNode) {
//if the target node is not given then use the body
var targetNode = targetNode || document.body;
//append the domFragment to the target
targetNode.appendChild(domFragment);
}
//return the buffer
return {
"add": add,
"flush": flush
}
}
//to make a buffer do this
var buffer = Buffer();
//to add elements to the buffer do the following
buffer.add(someNode1);
//continue to add elements to the buffer
buffer.add(someNode2);
buffer.add(someNode3);
buffer.add(someNode4);
buffer.add(someN...);
//when you are done adding nodes flush the nodes to the containing div in the dom
buffer.flush(myContainerNode);