在javascript中找到tbody行的最佳方法是什么?正则表达式还是......?

时间:2010-09-19 02:53:01

标签: javascript jquery regex

我想要做的是过滤一个表,只显示包含输入到文本框中的值的给定值的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将返回此示例数据的第一行和第三行,但我认为您已经想到了...

HELP?

3 个答案:

答案 0 :(得分:1)

每次使用这么多DOM元素时,主要的性能影响通常都是渲染,因为每次修改DOM中的内容时,浏览器都会重新渲染页面。除非您修改DOM之外的元素,否则这会将渲染性能转换为O(n ^ 2)。有几种方法可以像克隆和DOM数组一样做到这一点。要使用克隆您clone要修改的元素,请修改克隆元素,然后使用replaceWith将它们插入到DOM中。 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

答案 1 :(得分: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');
}

答案 2 :(得分:0)

我认为最好对一组数据使用过滤函数,这些数据就是一个对象数组。然后,您从过滤后的数据提供程序重建表。

显示/隐藏表行存在固有问题,其中最重要的是不同浏览器(我看着你,IE)隐藏不同的事实。仅将行设置为visibility =“hidden”将无法执行您想要的操作。将它设置为display =“none”会,但是你会遇到问题。在这种情况下,您将显示样式设置为什么?当然不是“阻止”。将其设置为表行的行为与跨浏览器的行为不同。