【问题标题】:What's the best way to find tbody rows in javascript? Regex or ...?在 javascript 中查找 tbody 行的最佳方法是什么?正则表达式还是...?
【发布时间】:2010-09-20 01:46:02
【问题描述】:

我想要做的是过滤一个表格,仅显示包含给定值的 tbody 与输入到文本框中的值,并以斑马条纹图案显示过滤后的行。

斑马条纹很快,过滤通常很快,除了在有很多 tbody 的桌子上的第一个过滤器(比如 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 将返回此示例数据的第一行和第三行,但我认为您已经弄清楚了...

帮忙?

【问题讨论】:

    标签: javascript jquery regex


    【解决方案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

    【讨论】:

    • 即使交换也无法避免渲染问题。通过 innerHTML 将大表作为字符串完成仍然需要一段时间。
    • @Robusto 我更新了我的答案,显示在一张大桌子上的性能不同。
    • @gradbot:很好,我喜欢在这种情况下使用clone 的想法。不错的作品。然而,在某些时候隐藏/显示问题将进入等式。删除几行会导致所有其他行重新渲染,这会消耗周期和时间。
    • 所以...测试表明这个正则表达式版本要快得多。我还没有尝试过霍根的答案...
    • 由于上述原因,如果我的性能比这更好,我会感到震惊,但我的更改可能会使这更快!
    【解决方案2】:

    我认为对一组数据使用过滤函数会更好,这将是一个对象数组。然后你从过滤的数据提供者重建表。

    显示/隐藏表格行存在固有的问题,其中最重要的是不同的浏览器(我在看你,IE)的隐藏方式不同。仅仅将一行设置为 visibility="hidden" 不会做你想要的。将其设置为 display="none" 会,但是您在取回它时会遇到问题。在这种情况下,您将显示样式设置为什么?当然不是“阻止”。并将其设置为 table-row 跨浏览器的行为不同。

    【讨论】:

    • 好评论。我每次都考虑从头开始重建它,因为我周末一直在考虑这个问题,所以想得到一些意见。对此有什么想法吗?
    • 应该是jQuery用show()和hide()处理跨浏览器问题吧?
    • @drachenstein:这是我能想到的获得备用行颜色(斑马条纹)的唯一非笨拙方式。否则你必须每次都遍历它们,这可能比重建更麻烦。 @Hogan:据我所知,jQuery 会正确处理这个问题,但它仍然是一种痛苦和消耗,而且渲染可能不会比重建快多少。
    • 我个人不会将 2000 行加载到浏览器中,而是使用 AJAX 来获取数据——但问题是基于一篇使用 jQuery 显示和隐藏行的文章——所以它是一个安全的赌注它有效。 jQuery 就是这样,它让疯狂的跨浏览器变得容易(在这种情况下可能更容易。)
    • @Hogan @Robusto ~ 加载多达 40k 行进行排序......我认为做我所有的重新渲染客户端比等待潜在的延迟数据库连接更快寻找我在浏览器中已有的东西。 (另外,主机页面是 asp.net,而我的合作开发人员在 AJAX 上还不够完善,所以我需要可支持的代码......)
    【解决方案3】:

    只是一个想法,这(双关语)更快吗?

    //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/3。

    另外,您是否真的需要在每一行上删除和添加一个类 - 如果它是隐藏的,您可以检查它是否需要知道它是否可见。

    使用 jQuery 选择器:

    //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');
    }
    

    【讨论】:

    • 以此作为我的灵感:net.tutsplus.com/tutorials/javascript-ajax/… 所以添加/删除类是他的想法。他使用过滤器类来抓取稍后被斑马处理的数据。我认为这可能是瓶颈。
    • 当然。正则表达式可能有点慢——当然你真的没有其他选择,除了尝试一个 jquery 选择器......
    • @drachenstern : 注意新代码 -- 如果没有正则表达式,你不需要 jQuery 的回调函数。
    • 时间限制是什么...我想测试这个,但还没有。当我有机会时,我会回来更新此状态
    猜你喜欢
    • 2016-05-18
    • 1970-01-01
    • 2011-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-23
    • 1970-01-01
    相关资源
    最近更新 更多