2010-09-19 52 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

相关问题