首页 \ 问答 \ 为什么分离和追加比直接更改html更有效?(Why is detaching and appending more efficient than changing html directly?)

为什么分离和追加比直接更改html更有效?(Why is detaching and appending more efficient than changing html directly?)

有人告诉我,当在DOM中插入多个元素时,首先分离目标元素,插入元素然后将其追加到DOM会更有效。 我想知道为什么。

例如,

HTML

<div id="main">
  <ul class="list"></ul>
</div>

jQuery的

var arrayOfElements = [$("<li> .... </li>"), $("<li> .... </li>"), ... , $("<li> ... </li>")]

# Appraoch 1
$(".list").html(arrayOfElements);

# Approach 2
$(".list").detach().html(arrayOfElements).appendTo(".main");

为什么appraoch 2更有效率,有多重要?


I was told that when inserting multiple elements into the DOM, it is more efficient to first detach the destination element, insert the elements, and then append it back to the DOM. I would like to know why.

For instance,

html

<div id="main">
  <ul class="list"></ul>
</div>

jQuery

var arrayOfElements = [$("<li> .... </li>"), $("<li> .... </li>"), ... , $("<li> ... </li>")]

# Appraoch 1
$(".list").html(arrayOfElements);

# Approach 2
$(".list").detach().html(arrayOfElements).appendTo(".main");

Why is appraoch 2 more efficient, and by how much significance?


原文:https://stackoverflow.com/questions/26767804
更新时间:2019-11-21 10:10

最满意答案

向DOM添加一系列元素时,每个元素都会触发浏览器重排页面。 将一个元素添加到已经准备好而不在DOM上的页面上,然后将其附加到DOM只会导致页面的一次重排。

来自: http//www-archive.mozilla.org/newlayout/doc/reflow.html

所有回流都有一个原因,它在回流状态对象中保持(并且可能变异,如下所述)。 回流原因控制框架在回流期间的反应方式,并且是以下之一:

文章接着列出了回流的原因,以下是其中一个原因:

增量,当帧树中的某些东西改变时; 例如,当从网络读取更多内容时,或某些脚本操纵DOM。 增量回流针对帧层次结构中的单个帧。 在增量回流期间,帧可以假设from above'' (for example, available width) have changed; instead, something计算的约束from above'' (for example, available width) have changed; instead, something from above'' (for example, available width) have changed; instead, something “框架内的from above'' (for example, available width) have changed; instead, something已经改变,这可能会对框架层次结构产生自下而上的影响。

至于性能改进,我会把它留给John Resig。

Browser         Normal (ms) Fragment (ms)
Firefox 3.0.1   90          47
Safari  3.1.2   156         44
Opera 9.51      208         95
IE 6            401         140
IE 7            230         61
IE 8b1          120         40

资料来源: http//ejohn.org/blog/dom-documentfragments/

你的例子虽然有些瑕疵。

var arrayOfElements = [$("<li>....</li>"), $("<li>....</li>"), $("<li>...</li>")];

应该写成:

var arrayOfElements = ["<li>....</li>", "<li>....</li>", "<li>....</li>"].join('');

其次

// Approach 1
$(".list").html(arrayOfElements);

在这两个例子之间,这个实际上可能更好。 为什么?

因为:

// Approach 2
$(".list").detach().html(arrayOfElements).appendTo("#main");

可能导致最多(并且可能会)2次回流。 一旦<ul> DOM <ul>从DOM中删除,一次将其附加到DOM。 Approach 1可能导致2次(或更多次)回流,因为.html必须删除当前子级,然后附加第二组。 决定因素是.html方法是顺序追加每个元素还是一次追加一个DOM元素。 但至少它更容易理解。 并且它最多可以从DOM中移除少量元素,从而可能减少回流的影响。

但是,这两种方法都优于以下方法:

var arrayOfElements = ["<li>....</li>", "<li>....</li>", "<li>....</li>"];
$('.list').children().remove();
for (var i = 0; i < arrayOfElements.length; i++) {
    $(arrayOfElements[i]).appendTo('.list');
}

When appending a series of elements to the DOM each triggers the browser to reflow the page. Adding one element to the page that has already been prepared while not on the DOM then appending that to the DOM only causes one reflow of the page.

From: http://www-archive.mozilla.org/newlayout/doc/reflow.html

All reflows have a reason, which is maintained in the reflow state object (and may mutate, as described below). The reflow reason controls how a frame reacts during a reflow, and is one of the following:

The article goes on to list the reasons for a reflow, the following is one such reason:

Incremental, when something in the frame tree changes; for example, when more content is read from the network, or some script manipulates the DOM. An incremental reflow is targeted at a single frame in the frame hierarchy. During an incremental reflow, a frame can assume that none of the constraints computed from above'' (for example, available width) have changed; instead, somethingwithin'' the frame has changed, which may have bottom-up impact to the frame hierarchy.

As for performance improvements I will leave that to John Resig.

Browser         Normal (ms) Fragment (ms)
Firefox 3.0.1   90          47
Safari  3.1.2   156         44
Opera 9.51      208         95
IE 6            401         140
IE 7            230         61
IE 8b1          120         40

Source: http://ejohn.org/blog/dom-documentfragments/

Your examples are somewhat flawed though.

var arrayOfElements = [$("<li>....</li>"), $("<li>....</li>"), $("<li>...</li>")];

Should be written as:

var arrayOfElements = ["<li>....</li>", "<li>....</li>", "<li>....</li>"].join('');

Secondly

// Approach 1
$(".list").html(arrayOfElements);

Between the two examples this one MAY actually be better. Why?

Because:

// Approach 2
$(".list").detach().html(arrayOfElements).appendTo("#main");

Can cause up to (and probably will) 2 reflows. Once when the <ul> is removed from the DOM and once when it is appended to the DOM. Approach 1 may cause 2 (or more) reflows, as .html will have to remove the current children and then append the second set. The determining factor will be if the .html method appends each element sequentially or all at once as one DOM element. But at very least it is easier to grok. And at best it removes one less element from the DOM potentially diminishing the effects of the reflow.

However both methods are preferable to the following:

var arrayOfElements = ["<li>....</li>", "<li>....</li>", "<li>....</li>"];
$('.list').children().remove();
for (var i = 0; i < arrayOfElements.length; i++) {
    $(arrayOfElements[i]).appendTo('.list');
}
2014-11-06

相关问答

更多

datetime.strptime( '2017-01-12T14:12:06.000-0500', '%Y-%间- %的dT%H:%M:%S%F%Z')(datetime.strptime(‘2017-01-12T14:12:06.000-0500’,'%Y-%m-%dT%H:%M:%S.%f%Z'))

Python 2.7的解决方案 从评论中可以清楚地看出OP需要Python 2.7的解决方案。 显然,python 2.7的strptime中没有%z ,即使文档声称相反 ,引发的错误是ValueError: 'z' is a bad directive in format '%Y-%m-%dT%H:%M:%S.000%z' 。 要解决此问题,您需要先解析没有时区的日期,然后再添加时区。 不幸的是,您需要为此子类化tzinfo 。 这个答案是基于这个答案 from datetime import

我刚刚安装了VS.NET 2003,这使我的新版本(2005/2008)瘫痪了(I have just installed VS.NET 2003 which left my newer versions (2005/2008) crippled)

rifferte是正确的,因为最安全的是安装在另一个它们被释放。 此时可能最好的做法是修复Visual Studio 2008安装。 您可以通过“控制面板” - >“添加删除程序”菜单执行此操作。 这应该可以解决您所看到的问题。 rifferte is correct in that it's safest to install in the other they are released. Probably the best thing to do at this point is to re

SQL Server 2005上的SSRS 2008 Reporting Services(SSRS 2008 Reporting Services on SQL Server 2005)

是否可以在安装了SQL Server 2005的站点上安装SSRS 2008 [stand alone]。 没有。没有SSRS安装。 Is it possible to install SSRS 2008 [stand alone] on a site that has SQL server 2005 installed. No. There is no SSRS-only installation.

TFS Build Server从2008年升级到2012年(TFS Build Server upgrade from 2008 to 2012)

我已经设法通过在Build Targets文件中复制BuildAgentUri属性来解决上述问题,然后它工作了。 可从以下URL获得更多解释: https://social.msdn.microsoft.com/Forums/vstudio/en-US/389da76d-4637-4556-a68f-bafb9febc8ea/how-to-troubleshoot-trror-in-ant-build-with-tfs-2012?论坛=三通 I have managed to resolve t

2012年之后安装的VS 2010以及用于Web发布的目标文件的MSbuild路径现在不正确(Installed VS 2010 after 2012 and MSbuild paths to target file for web publish is incorrect now)

最简单(但很冗长)的解决方案是修复visual studio: 从Windows的“程序和功能”窗口修复Visual Studio 2012 重新应用Visual Studio Update 4 这将确保最新的位回到它们应该的位置。 The easiest (though lengthy) solution will be to repair visual studio: Repair Visual studio 2012 from the Windows' Programs and Featu

从vb6迁移到vb2005,vb2008,vb2010之间的差异(Differences between migrating from vb6 to vb2005, vb2008, vb2010)

我认为定位更高版本会稍微容易一些。 我相信为Visual Studio 2005添加了PowerPack 3.0 :它包括对模拟VB6 Printer对象和形状控件的额外支持。 任何读过我关于VB6迁移的其他答案的人都应该现在停止阅读,因为我之前已经说过了......但我认为这是相关的,所以无论如何我都会再说一遍。 通过截屏视频查看Microsoft UK 建议 ,解释.Net迁移的5个基本选项。 决定哪个是最好的。 人们可能会建议你在.Net中从头开始重写。 要小心谨慎 - 你说你的代码库很大

使用_TOTAL_在数据表中进行条件格式设置(Conditional Formatting in Datatables using _TOTAL_)

我设法搞清楚了! 使用fnInfoCallback属性我可以评估iTotal属性,并根据下面显示的if语句,我可以决定要输出什么字符串! 用法: $("#sqepMatrix").dataTable({ "bJQueryUI": true, "bPaginate": false, "sPaginationType": "full_numbers", "fnInfoCallback": function (oSettings, iTotal) {

使用C#合并Office 2007或2003中的字段(Merge fields in Office 2007 or 2003 using C#)

我有一份工作做这件事一会儿。 我们使用的是Word Automation,但是很痛苦(因为Word会做一些疯狂的事情,比如弹出一个会破坏你的代码的模态对话框)。 我们开始使用Aspose库。 我发现这个领域相当合理且功能齐全(对合并领域有很好的支持)。 然而,它是商业的。 (我跟公司没什么关系 - 我刚用过他们的软件) 编辑:如果您只需要Word 2007支持,请不要打扰这些人; 有很多免费图书馆。 但是对旧版本的支持更难找到 I had a job doing this stuff a whi

相关文章

更多

最新问答

更多
  • 用于Json解析的Phonegap插件(Phonegap Plugin for Json parsing)
  • ActionScript 2加载另一个加载其他文件的SWF - 相对路径/网址问题(ActionScript 2 load another SWF that loads other files - relative path/url problem)
  • 使用sql将一些列值放入新列中(put some column values in a new column using sql)
  • 在iOS中为NivevehGL设置View的背景图像(Setting the background image of the View for NivevehGL in iOS)
  • 从普通的C#开发人员到普通的Java开发人员需要多长时间?(How long will take from an average C# developer to an average Java developer?)
  • 通过datetimefield SQL Server加入(Joining by datetimefield SQL Server)
  • Python中是否有任何智能打印方法?(Are there any smart print methods in Python?)
  • R中关闭另一个表[关闭](Removing one table from another in R [closed])
  • 枚举数字(Enumerating digits)
  • 我想从现有数组中获取新数组,其中key是旧数组的重复值,value是重复计数?(I want new array from existing array with key as repeated value from old array and value as repeated count?)
  • 如何在不创建实例的情况下调用类方法(How to call a class method without creating an instance)
  • wxHaskell中嵌入的图像(Embedded images in wxHaskell)
  • 蚂蚁战争任务如何运作?(How does the ant war task work?)
  • Windows Workflow 4中的人员活动支持(Human activity support in Windows Workflow 4)
  • 在Firebug的Net Panel中缺少'DomContentLoaded'和'加载'时间信息(Missing 'DomContentLoaded' and 'load' time information in Firebug's Net Panel)
  • 如何抓取页面以查看复选框/广播/文本输入并检测其原始值的更改?(How can I crawl the page for checkbox/radio/text inputs and detect changes to their original values?)
  • Document.ready不起作用(Document.ready won't work)
  • Java序列化问题(Java serialization problem)
  • Javascript:如何在页面刷新时处理令牌验证?(Javascript: How should I handle token verification on page refresh?)
  • 数据库安全:中间“to_be_deleted”列/表?(Database safety: Intermediary “to_be_deleted” column/table?)
  • 使用mayavi时如何删除scalar_cut_plane中的红框和白色箭头?(How to remove the red frame and white arrow in scalar_cut_plane when using mayavi?)
  • 如何延迟MainPage,所以它在加载数据后启动?(How to delay MainPage, so it starts after data is loaded?)
  • 按Enter键更改EditText(Press Enter to change EditText)
  • 使用libavcodec解码时可以裁剪帧大小吗?(Can the frame size be cropped during decoding using libavcodec?)
  • Performance_Python根据元组的3个元素中的2个获得2个元组列表的并集(Performance_Python get union of 2 lists of tuple according to 2 out of the 3 elements of the tuple)
  • 为什么法线会随相机旋转?(Why normals rotate with camera?)
  • 如何将Intent与ListView一起使用?(How do I use Intents with ListView?)
  • html_safe无法使用rails(html_safe not working with rails)
  • 录制没有单独的程序或库的opengl视频(record opengl video without separate program or library)
  • 滚动到特定视图(Scroll to particular view)