2010-09-19 48 views
0

我想要做的是過濾一個表格,只顯示包含給定值的tbody與輸入到文本框中的值,並顯示斑馬條紋圖案中的過濾行。什麼是在javascript中找到tbody行的最佳方式?正則表達式還是...?

斑馬條紋很快,過濾通常很快,除了在很多tbodys的桌子上的第一個過濾器(比如2000 tbody?)...我還沒有測量過第一個可見的減速和避風港「T測試通過數量的速度,但在Firefox和Chrome)

首先JS很慢:

//filter results based on query 
function filter(selector, query) { 
    var regex = new RegExp(query, "i"); // I did this from memory, may be incorrect, but I know the thing works, the problem is the next part, cos on 5 rows it's fast 
    $(selector).each(function() { 
    (regex.test($(this).text())) < 0) ? $(this).hide().removeClass('visible') : $(this).show().addClass('visible'); 
    }); 
} 
// then after this I recall the zebra function, which is fast. 

然後將樣本數據:

<table> 
<thead> 
    <tr> 
    <th>value to find 1</th> 
    <th>value to find 2</th> 
    </tr> 
</thead> 
<tbody> 
    <tr> 
    <td>12345</td> 
    <td>67890</td> 
    </tr> 
    <tr> 
    <td>empty for now, while testing</td> 
    <td>may contain other info later</td> 
    </tr> 
</tbody> 
<tbody> 
    <tr> 
    <td>23456</td> 
    <td>78901</td> 
    </tr> 
    <tr> 
    <td></td> 
    <td></td> 
    </tr> 
</tbody> 
<tbody> 
    <tr> 
    <td>45678</td> 
    <td>90123</td> 
    </tr> 
    <tr> 
    <td></td> 
    <td></td> 
    </tr> 
</tbody> 

... /ad nauseum, for 2000 rows + 

<tfoot> 
</tfoot> 
</table> 

因此,例如,試圖匹配值123將返回此示例數據的第一和第三行,但我認爲你已經想通了...

幫助?

回答

1

任何時候處理這​​些DOM元素時,主要的性能影響通常都是渲染,因爲每次在DOM中修改某些內容時,瀏覽器都會重新渲染頁面。除非您修改DOM之外的元素,否則這會將渲染性能轉換爲O(n^2)。有幾種方法可以做到克隆和DOM數組。要使用您想要修改的元素的克隆clone,請修改克隆的元素,然後將它們插入DOM中,並使用replaceWith。 DOM數組只是包含DOM元素的標準JavaScript數組。您可以將一組DOM元素傳遞給jQuery而不是選擇器。這是我的測試使用你的html副本的輸出。我正在使用jQuery 1.4.2。

// Using chrome 6.0.472.62 
Number of <td> elements: 9524 
Optimized Time: 232ms 
Normal Time: 21669ms 

其他現代瀏覽器有不同的性能特徵。

// Using IE8 
Number of <td> elements: 9524 
Optimized Time: 1506ms 
Normal Time: 4179ms 

// Using Firefox 4 Beta 
Number of <td> elements: 9524 
Optimized Time: 698ms 
Normal Time: 2644ms 

您可以看到O(n^2)渲染是如何真正開始累加起來的。這是我的測試程序減去數千個複製的html元素。

$(document).ready(function(){ 
    console.log("Number of <td> elements: " + $("td").length); 

    $('input[value=clone]').click(function(){ 
    function filter(selector, query) { 
     var regex = new RegExp(query, "i"); 
     var temp = $("table").clone(); 
     var hide = []; 
     var show = []; 
     $(selector, temp).each(function() { 
     if (regex.test($(this).text())) { 
      hide.push(this); 
     } else { 
      show.push(this); 
     } 
     }); 
     $(hide).hide().removeClass('visible'); 
     $(show).show().addClass('visible'); 
     $("table").replaceWith(temp); 
    } 
    var start = (new Date).getTime(); 
    /* Run a test. */ 
    filter("td","12345"); 
    var diff = (new Date).getTime() - start; 
    console.log("Optimized Time: " + diff + "ms"); 
    }); 

    $('input[value=normal]').click(function(){ 
    function filter(selector, query) { 
     var regex = new RegExp(query, "i"); 
     $(selector).each(function() { 
     if (regex.test($(this).text())) { 
      $(this).hide().removeClass('visible'); 
     } else { 
      $(this).show().addClass('visible'); 
     } 
     }); 
    } 
    var start = (new Date).getTime(); 
    /* Run a test. */ 
    filter("td","12345"); 
    var diff = (new Date).getTime() - start; 
    console.log("Normal Time: " + diff + "ms"); 
    }); 
}); 

如果您不想克隆的另一個選項是分離正在使用的元素,然後在完成後重新附加它們。見detach

+0

即使交換,也無法避免呈現問題。通過innerHTML以字符串形式完成的大表格仍需要一段時間。 – Robusto 2010-09-19 04:24:09

+0

我喜歡這個技巧,我得試試這個...... – jcolebrand 2010-09-19 10:54:04

+0

@Robusto我更新了我的答案,在大桌子上顯示了不同的表現。 – gradbot 2010-09-19 17:21:29

0

只是一個想法,這是(雙關語意圖)更快?

//filter results based on query 
function filter(selector, query) { 
    var regex = new RegExp(query, "i"); // I did this from memory, may be incorrect, but I know the thing works, the problem is the next part, cos on 5 rows it's fast 
    $(selector).each(function() { 
    me = $(this); 
    (regex.test(me.text())) < 0) ? me.hide().removeClass('visible') : me.show().addClass('visible'); 
    }); 
} 
// then after this I recall the zebra function, which is fast. 

應該減少至少一個行按2/3rds常量。

另外,你是否真的需要刪除並在每一行添加一個類 - 如果它是隱藏的,你可以檢查,如果你需要知道它是否可見或不。

使用jQuery selectory:

//filter results based on query 
// all elements in selector must not have class visible set 
function filter(selector, query) { 
    var newSel = selectory+":contains('"+query+"')"; 
    $(newSel).show().addClass('visible'); 
} 

//filter results based on query 
// safe version... hides all elements first. 
function filter(selector, query) { 
    $(selector).hide().removeClass('visible'); 

    var newSel = selector+":contains('"+query+"')"; 
    $(newSel).show().addClass('visible'); 
} 
+0

使用這個作爲我的靈感:http://net.tutsplus.com/tutorials/javascript-ajax/using-jquery-to-manipulate-and-filter-data/,以便添加/刪除類是他的想法。他使用過濾器類來獲取稍後斑馬的數據。我認爲這可能是瓶頸,因爲它是。當然是 – jcolebrand 2010-09-19 03:12:37

+0

。正則表達式可能會有點慢 - 當然你真的沒有任何其他的選擇,除了嘗試一個jQuery選擇器... – Hogan 2010-09-19 03:22:31

+0

我會在星期一測試... – jcolebrand 2010-09-19 03:34:44

0

我認爲這將是更好地使用的過濾器功能的一組數據的,這將是對象的數組。然後你從過濾的數據提供者重建表格。

顯示/隱藏表格行存在固有的問題,其中最重要的是不同的瀏覽器(我在看你,IE)的隱藏不同。僅僅設置一行到可見性=「隱藏」將不會做你想要的。將其設置爲display =「none」將會,但是在返回時遇到問題。在這種情況下,你將顯示樣式設置爲什麼?當然不是「阻止」。並將其設置爲表格行的行爲不同於跨瀏覽器。

+0

好評。我已經考慮過每次從頭開始重新構建它,因爲我在週末考慮過這個問題,所以想獲得一些意見。對此有任何想法? – jcolebrand 2010-09-19 03:11:49

+0

應該是這樣的情況,jQuery處理與show()和hide()正確的跨瀏覽器問題? – Hogan 2010-09-19 03:12:46

+0

@drachenstein:這是我能想到的唯一一種非kludgey方式來獲得交替行顏色(斑馬條紋)。否則,每次都必須遍歷它們,這可能比重建更麻煩。 @Hogan:就我所知,jQuery可以正確處理這些問題,但這仍然是一種痛苦和流失,渲染可能不會比重建速度快得多。 – Robusto 2010-09-19 03:32:07

相關問題