简体   繁体   English

为什么这个jQuery代码比这个慢得多?

[英]Why this jQuery code is much slower than this one?

I have 2 Divs like columns every column has inner divs with different content like this: 我有2个Divs,例如各列,每列都有内部div,内容不同,如下所示:
image for the HTML layout HTML布局的图像
(I will call the "inner div" as "line"). (我将“内部div”称为“行”)。

the text of line#1 in column#1 is the translation of line#1 in column#2, 第1列中第1行的文本是第2列中第1行的翻译,
the text of line#2 in column#1 is the translation of line#2 in column#2, 第1列中第2行的文本是第2列中第2行的翻译,
the text of line#3 in column#1 is the translation of line#3 in column#2, 第1列中第3行的文本是第2列中第3行的翻译,
and so on. 等等。
What I need to achieve is: 我需要实现的是:
line#1 in column#1 should be aligned to line#1 in column#2, 第1列中的第1行应与第2列中的第1行对齐,
line#2 in column#1 should be aligned to line#2 in column#2, 第1列中的第2行应与第2列中的第2行对齐,
line#3 in column#1 should be aligned to line#3 in column#2, 第1列中的第3行应与第2列中的第3行对齐,
and so on. 等等。

so instead of this: non-aligned lines I want it to be like this aligned (equal Heights) lines 所以代替这个: 不对齐的线,我希望它像这样对齐(等高)的线

and I achieved that with this code 我用这段代码实现了

  var t0 = performance.now();
  var leftArray = $('#left .line').map(function(i) {
    return $(this).height();
  });
  var rightArray = $('#right .line').map(function(i) {
    return $(this).height();
  });
  for (var i = 0; i < leftArray.length; i++) {
    if (leftArray[i] < rightArray[i]) {
     $('#left .line').eq(i).css('height', rightArray[i])
    } else if (leftArray[i] > rightArray[i]) {
     $('#right .line').eq(i).css('height', leftArray[i])
   }
 }

which works good and fairly fast for 2 columns divs it takes about (55ms for 300 lines/column). 这对于2列divs来说效果很好而且相当快,大约需要花费55ms(300行/列)。

Now I want to change the code to support more number of columns (Imagine I have 3 or 4 columns beside each other and want to align each line with it's corresponding.) 现在,我想更改代码以支持更多列(想象一下,我彼此之间有3或4列,并希望将每一行与其对应的行对齐。)

so I changed the code to get lines with the same index from each column and used Math.max to calculate the max line height and apply it to all lines with that index, like this 因此,我更改了代码以从各列中获取具有相同索引的行,并使用Math.max计算最大行高并将其应用于具有该索引的所有行,如下所示

    //number of lines/column
    var column_lines_count =$('.lines').get(0).childElementCount;

    var elementHeights,target,maxHeight;
    for (var i = 1; i < column_lines_count; i++) {

     //get lines with the same index from each column
       target = $('[data-row="'+i+'"]');

    //retun height for each line
       elementHeights = target.map(function() {
          return $(this).height();
       }).get();

      //get the max height
      maxHeight = Math.max.apply(null, elementHeights);

      //set the max heights for all lines with this index number 
      $('[data-row="'+i+'"]').css('height', maxHeight); 
    }   

but when I execute this function on the 2 columns with 3oo lines/column it takes over (2000ms). 但是,当我在3oo行/列的2列上执行此功能时,它将接管(2000ms)。

So I changed the code and used .reduce instead, which allows me to save the index of line with the maximum height so I can ignore it when setting max height to elements (other lines) 因此,我更改了代码并改用.reduce ,这使我可以以最大高度保存行的索引,以便在将最大高度设置为元素(其他行)时可以忽略它

Here is the code I used 这是我使用的代码

        //number of lines/column
        var column_lines_count =$('.lines').get(0).childElementCount

        var target,realArray,maxHeight,index_max_height,next_h=0;
        for (var i = 1; i < column_lines_count; i++) {

         //get lines with the same index from each column
         target = $('[data-row="'+i+'"]');

         //Convert to array so we can use reduce
         realArray =  $.makeArray( target );

         //variable to save the index of the line that has the maximum height, so we don't have to set the height for it. 
         index_max_height=0

           /*
           * Reduce=>
           * intial value => $(realArray[0]).height()
           * next is represents the line
           * index = index of that line
            */  
           maxHeight = realArray.reduce(function(biggerHeight, next,index) {
             next_h = $(next).height();
             if(biggerHeight > next_h){
               return biggerHeight;
             } else{
               index_max_height =index;
               return next_h; 
             }
           }, $(realArray[0]).height());        

       /*
        *for elements (lines) that has index != index of max_height line - set the max height
        *
        */
        $.map( target, function( a, index ) {
            if(index != index_max_height){
              $(a).css('height', maxHeight);    
          }
        });

     }  

with this code it takes (on the 2 columns with 3oo lines/column) approx. 使用此代码,大约需要2列(每行3oo行)。 (1400ms). (1400毫秒)。

here is a fiddle with the 3 cases: 这是三种情况的小提琴:
https://jsfiddle.net/gc4xL36g/ https://jsfiddle.net/gc4xL36g/

Why the last 2 functions are much slower then the first one? 为什么后两个功能比第一个慢很多? and how I can improve the code if I have more than 2 columns? 以及如果我有超过2列,如何改善代码?

Update: 更新:
///////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////// ///////////////
as @Icepickle mentioned in his comment 正如@Icepickle在他的评论中提到的

selections are expensive 选择很昂贵

so I changed the code and use only one selector outside the loop and save it in variable which used inside the loop. 所以我更改了代码,在循环外仅使用了一个选择器,并将其保存在循环内使用的变量中。 it save some milliseconds but it still far from the code number one and I think the most part takes time is calculating the max height between the corresponding lines which I use reduce to implement, I appreciate if there is a suggestion to do this faster 它节省了几毫秒的时间,但距离代码1仍然很远,我认为大部分时间是在计算我使用reduce来实现的相应行之间的最大高度,如果有建议可以更快地执行此操作,我将不胜感激

Here is the new code: 这是新代码:

  var number_of_columns = $('.lines').length;     
  var lines = $('.line');
  var column_lines_count =lines.length/2;
  var realArray,maxHeight,index_max_height,next_h=0;

  for (var i = 1; i < column_lines_count; i++) {
    var corresponding_lines = [];
    var mindex;
    for(var j=0; j < number_of_columns; j++){
      mindex = i-1+(j*column_lines_count);
      corresponding_lines.push(lines[mindex]);
     }

     //Convert to array so we can use reduce
     realArray =  $.makeArray( corresponding_lines );

     //variable to save the index of the line that has the maximum height, so we don't have to set the height for it. 
      index_max_height=0


    /*
     * Reduce=>
     * intial value => $(realArray[0]).height()
     * next is represents the line
     * index = index of that line
     */

    maxHeight = realArray.reduce(function(biggerHeight, next,index) {
    next_h = $(next).height();
    if(biggerHeight > next_h){
        return biggerHeight;
    } else{
       index_max_height =index;
       return next_h; 
    }
    }, $(realArray[0]).height());       

    /*
     *for elements (lines) that has index != index of max_height line - set the max height
     *
     */
     $.map( corresponding_lines, function( a, index ) {
      if(index != index_max_height){
        $(a).css('height', maxHeight);  
      }
     });

    }   

As suggested by @DanielBeck 正如@DanielBeck建议的那样

Precalculate those heights in an array instead of reading them from the DOM every time 预先计算数组中的高度,而不是每次都从DOM中读取它们

solve the problem, 解决这个问题,
Here is the new code which become faster more than the first code 这是新代码,其速度比第一个代码快

 var number_of_columns = $('.lines').length;

 var lines = $('.line');
 var column_lines_count =lines.length/number_of_columns;
 var leftArray = lines.map(function(i) {
     return $(this).height();
 }); 
 var realArray,maxHeight;

 for (var i = 1; i < column_lines_count; i++) {
      var corresponding_lines = [];
      var mindex;
      for(var j=0; j < number_of_columns; j++){
          mindex = i-1+(j*column_lines_count);
           corresponding_lines.push(leftArray[mindex]);
     }

    //Convert to array so we can use reduce
     realArray =  $.makeArray( corresponding_lines );


   maxHeight = realArray.reduce(function(biggerHeight, next,index) {   
      if(biggerHeight > next){
        return biggerHeight;
      } else{
        return next; 
      }
    }, realArray[0]);       

    $('[data-row="'+i+'"]').css('height', maxHeight);   
  }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM