Javascript &引用;虚拟的;dom操纵?

Javascript &引用;虚拟的;dom操纵?,javascript,jquery,dom,dom-manipulation,Javascript,Jquery,Dom,Dom Manipulation,我知道执行多个dom操作是不好的,因为它会强制进行多个重绘 即: $('body')。追加(“”) .append(“”) .append(“”) .附加(“”); 相反,更好的做法显然是: $('body').append('<div><div></div><div></div><div></div><div></div></div>'); $('body')。追加(“”

我知道执行多个dom操作是不好的,因为它会强制进行多个重绘

即:

$('body')。追加(“”)
.append(“”)
.append(“”)
.附加(“”);
相反,更好的做法显然是:

$('body').append('<div><div></div><div></div><div></div><div></div></div>');
$('body')。追加(“”);
但我对虚拟操作很好奇

即:

$('').append('')
.append(“”)
.append(“”)
.append(“”)
.附于(“主体”);
它仍然很糟糕吗?显然,多次调用函数会带来一些开销,但是会有严重的性能问题吗


我这样问的原因是:

var divs = [
    {text: 'First',  id: 'div_1', style: 'background-color: #f00;'},
    {text: 'Second', id: 'div_2', style: 'background-color: #0f0;'},
    {text: 'Third',  id: 'div_3', style: 'background-color: #00f;'},
    {text: 'Fourth', id: 'div_4', style: 'background-color: #f00;'},
    {text: 'Fifth',  id: 'div_5', style: 'background-color: #0f0;'},
    {text: 'Sixth',  id: 'div_6', style: 'background-color: #00f;'}
];

var element = $('<div />');

$.each(divs, function(i,o){
    element.append($('<div />', o));
});

$('body').append(element);
var divs=[
{text:'First',id:'div_1',style:'background color:#f00;'},
{text:'Second',id:'div_2',style:'background color:#0f0;'},
{text:'Third',id:'div_3',style:'background color:#00f;'},
{text:'Fourth',id:'div_4',style:'background color:#f00;'},
{text:'Fifth',id:'div_5',style:'background color:#0f0;'},
{text:'Sixth',id:'div_6',style:'background color:#00f;'}
];
变量元素=$('');
$。每个分区、功能(i、o){
元素。追加($('',o));
});
$('body')。追加(元素);
假设divs数组来自描述表单的数据库表(好的,我在示例中使用div,但它可以很容易地替换为输入)或类似的内容

或者使用我们的“推荐”版本:

var divs = [
    {text: 'First',  id: 'div_1', style: 'background-color: #f00;'},
    {text: 'Second', id: 'div_2', style: 'background-color: #0f0;'},
    {text: 'Third',  id: 'div_3', style: 'background-color: #00f;'},
    {text: 'Fourth', id: 'div_4', style: 'background-color: #f00;'},
    {text: 'Fifth',  id: 'div_5', style: 'background-color: #0f0;'},
    {text: 'Sixth',  id: 'div_6', style: 'background-color: #00f;'}
];

var element = '<div>';

$.each(divs, function(i,o){
    element += '<div ';

    $.each(o, function(k,v){
        if(k != 'text'){
            element += k+'="'+v+'" ';
        }            
    });

    element += '>'+o.text+'</div>';

});

element += '</div>';

$('body').append(element);
var divs=[
{text:'First',id:'div_1',style:'background color:#f00;'},
{text:'Second',id:'div_2',style:'background color:#0f0;'},
{text:'Third',id:'div_3',style:'background color:#00f;'},
{text:'Fourth',id:'div_4',style:'background color:#f00;'},
{text:'Fifth',id:'div_5',style:'background color:#0f0;'},
{text:'Sixth',id:'div_6',style:'background color:#00f;'}
];
var元素=“”;
$。每个分区、功能(i、o){
元素+=''+o.text+'';
});
元素+='';
$('body')。追加(元素);

首先,尽管阅读这样的潜在性能影响非常好,但您应该始终从测量开始,看看您是否有问题

如果您无法察觉问题,请编写可读性最高的代码

如果你能察觉到一个问题,测量,改变和测量

话虽如此,您发布的最后一个示例涉及尚未写入DOM的元素,因此在
appendTo
将元素添加到DOM之前,不会进行重新绘制


如果您能够捕捉到第二个和第三个示例之间的速度差异,我会非常惊讶,如果您能够看到它们之间的任何主要差异,我也会非常惊讶。

如果您在附加节点时确实担心性能,那么您需要使用documentfragments。这将允许您在不重新绘制的情况下将元素附加到dom。约翰·迪普特对这个话题有自己的见解。他注意到性能提高了200-300%。我在我的一个应用程序中实现了documentfragments,可以证实他的说法

我认为,如果您开始发现此类代码是性能瓶颈,那么应该使用模板而不是DOM操作

但是,是的,在大多数情况下,使用文档片段方法(在连接到DOM之前将所有节点放入分离的节点中)会更快,几乎不会更慢


    • 在运行时,好的旧标记生成会发生什么?说真的,发生了什么事

      我同意@Sohnee关于可读性重要性的观点,但DOM操作是浏览器可以执行的最昂贵的操作之一。维护一个标记字符串的选项可以使其完全可读,并提供了一个可以忽略不计的用户体验改进

      在中,我们将在运行时创建一个10x100表——这对于数据分页来说是完全合理的(但不是目前最复杂的场景)。在运行最新版本Chrome的四核计算机上,直接DOM操作脚本需要60毫秒才能完成,而标记缓存则需要3毫秒

      这在我的设置上是一个无法区分的差异,但是坐在公司防火墙后面的那些可怜的数字处理者们又如何呢,他们仍然被迫使用过时的IE版本?如果DOM操作要求更重,需要进行属性操作和强制操作,该怎么办


      我想说的是,如果你想优化一些javascript,这是一个不错的开始。

      @nathan hayfield:“看起来还是不好”——为什么?“为什么不直接使用”——为什么不保持原样?@nathan hayfield:“快多了”???你能说出5次追加调用与串联调用的真正区别吗?该代码是为人编写的,只是在不符合性能要求的情况下才进行了优化。重新绘制可能会推迟到您处理的事件完成后进行。@millimoose,除非您调用引擎来计算您修改的节点的维度,然后它会重新出现-rendered@nathanhayfield请看我的edit.jQuery已经在内部使用了文档片段,当您执行类似于
      $(“”)
      @Juan:Ah的操作时,它就是这样做的。谢谢你指出这一点(对不起,我来自普通背景)。需要注意的是,这篇文章是4年前写的。在Chrome开发者工具中记录时间线告诉我,他的测试页面只执行过一次布局和绘制。但使用文档片段方法作为最佳实践(如果可能)并没有什么错,只要它不损害可读性。浏览器供应商都在努力使他们的浏览器超高速运行,所以实际上你只需要担心让你的代码易于理解和更改。我不确定你编写的应用程序有多大。但我一直在编写企业级应用程序,这些应用程序都是性能大亨,尽管我非常讨厌
      var divs = [
          {text: 'First',  id: 'div_1', style: 'background-color: #f00;'},
          {text: 'Second', id: 'div_2', style: 'background-color: #0f0;'},
          {text: 'Third',  id: 'div_3', style: 'background-color: #00f;'},
          {text: 'Fourth', id: 'div_4', style: 'background-color: #f00;'},
          {text: 'Fifth',  id: 'div_5', style: 'background-color: #0f0;'},
          {text: 'Sixth',  id: 'div_6', style: 'background-color: #00f;'}
      ];
      
      var element = $('<div />');
      
      $.each(divs, function(i,o){
          element.append($('<div />', o));
      });
      
      $('body').append(element);
      
      var divs = [
          {text: 'First',  id: 'div_1', style: 'background-color: #f00;'},
          {text: 'Second', id: 'div_2', style: 'background-color: #0f0;'},
          {text: 'Third',  id: 'div_3', style: 'background-color: #00f;'},
          {text: 'Fourth', id: 'div_4', style: 'background-color: #f00;'},
          {text: 'Fifth',  id: 'div_5', style: 'background-color: #0f0;'},
          {text: 'Sixth',  id: 'div_6', style: 'background-color: #00f;'}
      ];
      
      var element = '<div>';
      
      $.each(divs, function(i,o){
          element += '<div ';
      
          $.each(o, function(k,v){
              if(k != 'text'){
                  element += k+'="'+v+'" ';
              }            
          });
      
          element += '>'+o.text+'</div>';
      
      });
      
      element += '</div>';
      
      $('body').append(element);