Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 转换/移动大量DOM元素的最有效方法_Javascript_Jquery_Html_Css_Angularjs - Fatal编程技术网

Javascript 转换/移动大量DOM元素的最有效方法

Javascript 转换/移动大量DOM元素的最有效方法,javascript,jquery,html,css,angularjs,Javascript,Jquery,Html,Css,Angularjs,不久前,我为AngularJS建立了一个树表结构(使用了角材质) 我的目标是让它只在大屏幕(1280或更高)上工作,但现在我想更新它,让它在不限制数据的情况下在更小的设备(主要是平板电脑)上工作。出于性能考虑,我希望HTML尽可能简单(树表可以有1000多行,因此为单行创建更复杂的HTML将延长追加和呈现表行所需的时间(行是动态的,因此不仅仅是初始呈现)) 我想到了一个主意,我将保留“固定”部分,第一个单元格包含一个名称,第二个单元格包含所有度量,并将同步滚动 单行的当前HTML: <di

不久前,我为AngularJS建立了一个树表结构(使用了角材质)

我的目标是让它只在大屏幕(1280或更高)上工作,但现在我想更新它,让它在不限制数据的情况下在更小的设备(主要是平板电脑)上工作。出于性能考虑,我希望HTML尽可能简单(树表可以有1000多行,因此为单行创建更复杂的HTML将延长追加和呈现表行所需的时间(行是动态的,因此不仅仅是初始呈现))

我想到了一个主意,我将保留“固定”部分,第一个单元格包含一个名称,第二个单元格包含所有度量,并将同步滚动

单行的当前HTML:

<div class="tb-header layout-row">
  <div class="tb-title"><span>Name</span></div>
  <div class="tb-metrics">
     <div class="layout-row">
        <div class="tb-cell flex-10">812</div>
        <div class="tb-cell flex-7">621</div>
        <div class="tb-cell flex-4">76.5</div>
        <div class="tb-cell flex-7">289</div>
        <div class="tb-cell flex-4">46.5</div>
        <div class="tb-cell flex-7">308</div>
        <div class="tb-cell flex-4">49.6</div>
        <div class="tb-cell flex-7">390</div>
        <div class="tb-cell flex-4">48.0</div>
        <div class="tb-cell flex-7">190</div>
        <div class="tb-cell flex-4">23.4</div>
        <div class="tb-cell flex-7">0</div>
        <div class="tb-cell flex-4">0.0</div>
        <div class="tb-cell flex-8">6.4</div>
        <div class="tb-cell flex-8">0.0</div>
        <div class="tb-cell flex-8"></div>
     </div>
  </div>
不幸的是,当表包含更多行时,此解决方案的速度非常慢(我无法缓存行,因为它们是动态的)

在我的第二次尝试中,a尝试尽可能避免DOM操作。 为了实现这一点,我决定在dom中添加
标记,该标记包含应用于
.metrics>.layout行的css

解决方案:

function moveMetrics( offset ) {
  var ofx = offset < 0 ? (offset < -getMetricsScrollWidth() ? -getMetricsScrollWidth() : offset) : 0
    , style = $( '#tbMetricsVirtualScroll' )
    ;

  if ( !style.length ) {
    body.append( '<style id="tbMetricsVirtualScroll">.tb-metrics > * {transform: translateX(' + ofx + 'px)}</style>' );
    style = $( '#tbMetricsVirtualScroll' );
  } else {
    style.text( '.tb-metrics > * {transform: translateX(' + ofx + 'px)}' );
  }
  /*...*/
}
函数移动度量(偏移量){
变量ofx=offset<0?(offset<-getMetricsScrollWidth()?-getMetricsScrollWidth():offset):0
,style=$(“#tbMetricsVirtualScroll”)
;
如果(!style.length){
append('.tb metrics>*{transform:translateX('+ofx+'px)}');
样式=$('tbMetricsVirtualScroll');
}否则{
text('.tb metrics>*{transform:translateX('+ofx+'px)}');
}
/*...*/
}
但是,当表包含大量行时,速度似乎不会快很多。所以这不是DOM操作,但渲染/绘制视图似乎是这里的瓶颈

我试图创建某种虚拟卷轴,但由于不同数据集的树结构不同,并且可以有“无限”个级别(每行可以包含new
ng repeat
)中的子行),这是一项非常困难的任务

如果您能告诉我如何在不使用虚拟卷轴的情况下提高性能,我将不胜感激

编辑:

Chrome timeline的屏幕截图显示,滚动的大部分时间都被渲染所消耗(我猜这是因为复杂的DOM结构)

编辑2:

我不会说我实现了绝对平滑的滚动,但我发现了一些显著的性能改进(其中一些改进并不明显,在进行了如此小的更改后,结果比我预期的要好)

  • 简化类选择器:
    .tb header>.tb metrics>.tb cell
    .tb-specific cell
    慢得多(似乎解析更复杂的选择器需要更多的时间?)
  • 从变换的元素中删除不透明度和长方体阴影
  • 尝试将转换后的元素分发到新层(使用css
    将更改
    和/或
    translateZ(0)

    • 所以我自己也不是专家,但我确实有一些想法值得一提。 如果我理解正确,问题是这个项目需要越来越多的HTML元素,这会不断降低性能

      下面是3个js概念,我认为它们会对您有所帮助

      *动态创建html元素:

      let div = document.createElement('div');
      
      *动态地创建要用于元素的属性,并动态地分配这些属性

      function attributeSetter(atr){
         div.setAttribute('class', atr)
      }
      
      这样,您就可以在任何需要的地方调用该函数,并为其提供任何类 您要动态为其指定的名称。此外,可以根据需要多次使用div元素

      最后一个概念。您还可以动态添加预定义的类,假设它们已经在css中预定义,如下所示

      div.classList.add("my-class-name")
      
      还有一个可能派上用场的概念是去结构化

      let myClasses = ['flex-10', 'flex-7', 'flex-4', 'flex-9'] //etc
      let [flex10, flex7, flex4, flex9] = myClasses;
      
      这将把所有这些字符串转换为变量,您可以轻松地迭代并动态地将它们添加到attributeSetter函数中,如下所示:

      attributeSetter(flex10)
      

      无论你在哪里需要它。我不知道这是否有帮助,或者这是否回答了你的问题,但至少有一些想法。祝你好运:)

      我过去也有过类似的问题,因为我的桌子很大。因此,将UX方面的事情排除在等式之外——为了实现您的目标,可以采取以下措施。与其固定第一张桌子,移动其余的桌子,也许你可以试试另一种方法。Aka,将表放在溢出容器中,以允许在垂直滚动时使用
      translateY
      第一列表单元格进行水平滚动和移动

      按照我描述的方式,您可以检索第一个表格单元格的最大宽度(或者更好,设置一个固定的宽度),绝对将每个单元格放在左侧-但是要小心,相对容器应该在溢出的表格之外,在每行的第二个表格单元格上设置一个空白,等于第一个表格单元格,然后,垂直滚动时,添加负值
      translateY
      值。然后,选择器应易于访问“.layout row.table cell:first child”

      同样,对于较小的优化,不要使用
      .css()
      尝试使用
      .attr('style',value)
      。此外,我读到,您有动态内容,不能缓存它,但是,也许您应该考虑每次操作DOM时缓存一次。缓存的选定元素仍然比在每个scroll/touchmove事件中计算选择器要好


      最后但并非最不重要的一点是,您还可以添加某种去抖动技术,这样滚动就不会出现在每个滚动帧上,但可能每10帧出现一次-眼睛仍然看不见,或者在任何情况下都比在浏览器上瓶颈式地处理所有这些重绘事件要好。

      我建议查看虚拟重复,您应该使用material desi
      attributeSetter(flex10)