如何在非常长的HTML表格中隐藏列

4
我有一个拥有20列和约1000行的表格。我想基于筛选器显示/隐藏不同的列,即每个筛选器显示与该筛选器相关的列并隐藏无关的列。
我尝试了两种方法:
1)使用jQuery根据列的索引向THs和TDs添加“hide”类。由于必须将该类添加到要隐藏的每个单元格中,因此这种方法非常缓慢。
2)在表格顶部的COLGROUP中为COLs添加“hide”类。问题在于,当对COLs添加样式规则如“display: none”或“visibility: collapse”时,不是所有浏览器都将这些规则应用于表中相应的列,因为单元格不是COLs的子项。
有什么建议吗?

1
纯JS可以比jQuery表现得更好。如果没有人提供一个很好的答案,我会尝试一下。 - Beterraba
将表格分页,以减少记录数。 - nathan hayfield
5个回答

3

我认为最简单的方法是在jQuery中动态创建样式元素,使用以下CSS规则:

td:nth-child(n)
{
  display:none;
}

这里是演示

这是一段示例代码,你可以改进它。我只是在这里创建了一个非常简单的示例:

var myStyle = 'td:nth-child(column_index){display:none;}', 
    $myStyleElement = $(document.createElement('style'));

$myStyleElement.attr('id', 'dynamic_style');
$('head').append($myStyleElement);

$('#hide_column').click(function(e){
    $('style#dynamic_style').html(myStyle.replace('column_index', '3'));
});

$('#show_column').click(function(e){
    $('style#dynamic_style').html('');
});

请注意,通过创建样式元素,您将强制浏览器自身呈现页面,这种方式比任何JavaScript实现都更为优化。我的意思是,脚本中没有对元素的迭代。但是我不知道浏览器内部发生了什么。

这是一个非常棒的方法。OP在问题中提到表格大约有1000行(在文本中有明确说明,可能是你没有注意到)。 - Katie Kilian
@CharlieKilian 我在这里创建了一个测试用例(http://jsfiddle.net/Antindexer/7n2wg/3/),其中包含1320个元素,在Linux Chrome环境下运行非常快。 - Khamidulla
1
这是高效的。如果你将它与我的解决方案结合起来,你就可以摆脱奇怪的动态CSS生成了。我不是nth-child符号的忠实粉丝(它缺乏表现力),但这是一个合理的权衡。 - Halcyon
@FritsvanCampen 如果所有过滤器都可以预定义,那么您的方法是最好的。因此,请查看这里以获取其他情况的信息:https://dev59.com/4WEi5IYBdhLWcg3wwecN - Khamidulla

3

要隐藏整列,可以使用堆叠定义:

// HTML
<table id="my-table" class="no-filter">
  <tr>
    <td class="column column1">c1</td>
    <td class="column column2">c2</td>
    <td class="column column3">c3</td>
  </tr>
  // etc x1000
</table>

// CSS
table td.column { display: none; } /* by default all columns are hidden */
table.no-filter td.column { display: block; } /* no-filter shows _all_ columns */
table.filter1 td.column1 { display: block; }
table.filter2 td.column2 { display: block; }
table.filter3 td.column3 { display: block; }

如果您只想显示列1:

$("#my-table").removeClass("no-filter").addClass("filter1");

如果您想要显示列1 列3:
$("#my-table").removeClass("no-filter").addClass("filter1").addClass("filter3");

如果您需要一对多过滤器
table.filter4 td.column4,
table.filter4 td.column5,
table.filter4 td.column99 { display: block; }
/* filter 4 shows column 4 5 and 99 */

过滤器可以重叠:

table.filter5 td.column5 { display: block; }
table.filter6 td.column5,
table.filter6 td.column6 { display: block; }

假设您的过滤器是预定义的,并且您知道过滤器与列之间的映射关系。

小提示:我没有测试过,可能会有优先级问题。如果过滤器未正确应用,请将 td.columnX 更改为 td.column.columnX


+1 对于这个问题,你的回答方法很好。然而,如果你回顾一下我关于动态添加CSS规则的问题,你会发现我使用了一些不同的情况来使用CSS规则。 - Khamidulla
我对此进行了一些小改动(将过滤器更改为隐藏列),并进行了测试,速度非常快,可以肯定地说这是目前为止最好的答案。 - Jarvan
是的,这就是正确的方法。不是要贬低Frits的想法,但我在发布后也想到了类似的想法。刚刚实现了,效果非常好。感谢大家。 - dylanmac
非常好的解决方案。不过我在代码的 display:block; 部分遇到了一些问题,可能是因为我有几个 rowspan 和 colspan,所以当显示时我只是将其留空,当隐藏时使用 display:none,这样效果更好。 - Tiziano Mischi

1
您可以将每个列拆分为自己的表格。然后,您可以在代表该列的整个表格上设置display: none,这样该“列”就会被隐藏。我猜那样做会更好,尽管它感觉有点hackish。

3
诚然,这段代码相当笨拙。如果这是我的代码,我也不会喜欢它。我很想看看是否有更好的解决方案。 - Katie Kilian
3
对一个我承认并非完美的应对方法进行踩票?似乎有些严厉。 - Katie Kilian
因为这确实是一个可以在万不得已时使用的解决方案,所以我点了赞。 :-) - cosjav
你知道吗,我有点喜欢这个答案。这会对你的表格施加一些限制,即你必须固定每个单元格的尺寸。但是如果你这样做了,为什么不彻底摒弃表格呢?div更优秀 :P - Halcyon

0

仅仅使用jQuery循环所有的并隐藏列似乎不像你们想象的那么慢...

这里是我基于@Phoenix的演示进行测试的:

jsfiddle

这里是隐藏和显示代码:

$('#hide_column').click(function(e){
    $("tr").each(function(){$(this).children(":eq(2)").hide();})
});

$('#show_column').click(function(e){
    $("tr").each(function(){$(this).children(":eq(2)").show();})
});

这段代码的性能甚至比 @Phoenix 的答案还要快,虽然我认为他的答案看起来更好,也许我们想得太多了...


1
也许 Phoenix 的解决方案速度较慢是因为动态生成 CSS?如果您预定义筛选器到列的映射(这是一个合理的假设),则可以静态添加 CSS。我的直觉告诉我您的解决方案应该会更慢。顺便说一下,两者在这里表现非常出色,我看不到立即优化的必要性。 - Halcyon
@jarvaJiang请给我看证据,它有多好?你有比较吗?如果它足够快,我一定会点赞。 - Khamidulla
@Phoenix,请查看这个jsfiddle:http://jsfiddle.net/7n2wg/6/,它是基于你的jsfiddle演示的,在我的环境中(window server2008 x64,chrome),你的速度比我的慢了大约半秒钟。但两者都比Frits van Campen的慢,你的方法是正确的,但可能动态CSS不太好。 - Jarvan

0
怎么样给特定列的所有单元格添加一个类:class="column1",对于所有列都是如此。然后: $('.column1').hide();

这将遭受与任何jQuery相同的性能问题。真正的问题是,无论使用什么选择器,jQuery都必须搜索行。 - Katie Kilian
那么,我们可以这样做,编写类似以下的CSS规则:.table_hideCol-1 > td:first-child { display: none; } .table_hideCol-2 > td:nth-child(2) { display: none; } .table_hideCol-3 > td:nth-child(3) { display: none; } {...}然后,使用jQuery/Javascript添加类.table_hideCol-n即可。 - Álvaro Martínez

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接