2012-03-16 49 views
0

我有一個函數,檢查edit-error類的表的每一行中的每個單元格。如果在特定行的任何單元格中找到該單元格(單元格值未通過驗證),則從整行中刪除類別,並取消選中該行的第一個td中的複選框。在性能上掙扎如何將其更改爲使用for循環?

當有大量的行(1,000+)時,我在性能上掙扎不已,所以我想我可以嘗試循環,但我不是JavaScript專家,所以我正在尋找幫助。

原始代碼如下:

var checkErrors = function() { 
    $('#results tr:not(:first)').each(function() { 
     $('td:first input:checkbox', $(this)).attr('checked', 'checked'); 
     $(this).addClass('edit-submit'); 

     $(this).find('td').each(function() { 
      if ($(this).hasClass('edit-error')) { 
       $('td:first input:checkbox', $(this).parent('tr')).removeAttr('checked'); 
       $(this).parent().removeClass('edit-submit'); 
      } 
     }); 
    }); 
} 

該表具有的#results一個id。我首先要做的是檢查所有的複選框,並將edit-submit類添加到每一行,然後遍歷所有單元格檢查錯誤。

我在尋找任何有關此功能性能改進的幫助。

編輯

這本來是有意義的添加表HTML。對於道歉那就是:

<table id="results"> 
    <tbody> 
     <tr> 
      <th>&nbsp;</th> 
      <th>Policy Number</th> 
      <th>Quota Code</th> 
      <th>Contract Date</th> 
     </tr> 
     <tr> 
      <td><input type="checkbox"></td> 
      <td class="edit-error">ABC123%</td> 
      <td>123</td> 
      <td class="edit-error">99/99/9999</td> 
     </tr> 
     <tr class="edit-submit"> 
      <td><input type="checkbox" checked="checked"></td> 
      <td>ABC123</td> 
      <td>123</td> 
      <td>16/03/2012</td> 
     </tr> 
    </tbody> 
</table> 

這將在頁面上顯示:

 
-------------------------------------------------- 
| | Policy Number | Quota Code | Contract Date | 
-------------------------------------------------- 
| | ABC123%  | 123  | 99/99/9999 | 
-------------------------------------------------- 
| X | ABC123  | 123  | 16/03/2012 | 
-------------------------------------------------- 
+0

':first'是非標準的CSS,這意味着jQuery不能使用可用的(快速)本機選擇器。嘗試刪除':first'並使用'.eq(0)'代替(和':not(:first)' - >'.slice(1)')。 – pimvdb 2012-03-16 10:11:38

+0

我仍然想知道如果使用for循環會比jQuery .each()函數更快。有人會同意我的意見或正在使用.each()的方式去? – 2012-03-16 10:42:26

+1

是的,plain for循環一定比'.each()'快。我在回答中包含了一種方法。但是,在你的代碼中還有其他一些東西可以提高效率,所以我將最後一次優化循環本身。 – nnnnnn 2012-03-16 10:59:20

回答

1

有幾種方法,以加快您的代碼無需進入純JS for循環。僅舉幾例:

  • 你已經有外.each()循環中當前行的引用,因此使用,而不是內部循環中調用$(this).parent()
  • 如果您只想處理具有特定類的td元素,則可以將該類包含在選擇器中,而不是調用.hasClass()
  • 避免多次調用相同的選擇器,方法是存儲對返回的jQuery對象的引用和/或通過鏈接。
  • 當提供上下文作爲$()的第二個參數時,您可以直接傳遞DOM元素或this,無需將其包裝在另一個$()調用中。
  • 如果您知道總會有一個複選框,您可以直接取消選中以保存函數調用。

所以:

var checkErrors = function() { 
    $('#results tr:not(:first)').each(function() { 
     var $tr = $(this), 
      cb = $('td:first input:checkbox', this)[0]; 

     cb.checked = true; 

     $tr.addClass('edit-submit') 
      .find('td.edit-error').each(function() { 
       cb.checked = false; 
       $tr.removeClass('edit-submit'); 
      }); 
    }); 
}; 

但是,是不是需要對TDS內循環在所有的,因爲你只需要測試是否有與錯誤類的行中的任何TDS - 你不實際上並不需要全部循環。加上良好的措施下面是使用一個for循環,而不是.each()一個辦法 - 請注意,就可避免複雜不-第一選擇,如果你簡單地從第二年起選擇所有的行,然後循環:

var checkErrors = function() { 
    var $rows = $('#results tr'), 
     i; 
    for (i = 1; i < $rows.length; i++) { 
     var $tr = $rows.eq(i), 
      cb = $tr.find('td:first input:checkbox')[0]; 

     if ($tr.find('td.edit-error').length === 0) { 
      cb.checked = true; 
      $tr.addClass('edit-submit'); 
     } else { 
      cb.checked = false; 
      $tr.removeClass('edit-submit'); 
     }; 
    } 
}; 
0

嘗試設置變量$(本)。你也需要使用find('td')? $('td',this)會做同樣的事情,但效率更高?

0

試試這個:

$.each($('#results .edit-error').parent(),function(){ 
      $(this).removeClass('edit-submit').find('td:first-child input:checkbox').removeAttr('checked'); 
}); 
0

使用變量$(本)。

你的選擇也得以改善:不是$('#this', '#that'),使用$('#that').find('#this')

這裏是一個改進版本,這些優化。

var checkErrorsOptimized = function() { 

    $('#results tr:not(:first)').each(function() { 
     var $this = $(this);  

     $this.find('td:first input:checkbox').attr('checked', 'checked'); 
     $this.addClass('edit-submit'); 

     $this.find('td').each(function() { 
      var $that = $(this); 
      if ($that.hasClass('edit-error')) { 
       $that.parent('tr').find('td:first input:checkbox').removeAttr('checked'); 
       $that.parent().removeClass('edit-submit'); 
      } 
     }); 
    }); 
} 

你可以看到它在此的jsfiddle(使用Firebug分析):http://jsfiddle.net/5kBsU/3/

+0

謝謝rohk你能解釋爲什麼做$('#that')。find('#this')好於$('#this','#that')嗎?我一直認爲最好是在選擇器中定義範圍。 – 2012-03-16 14:11:48

+1

http://shichuan.github.com/javascript-patterns/(在jQuery模式部分=>上下文和查找 - 使用查找上下文) – 2012-03-16 14:37:42

+0

感謝您的鏈接,通常是一個有趣的閱讀。我已將其加入書籤以吸取教訓。 – 2012-03-16 15:20:09