You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何简化带互斥条件的表格筛选器实现,提升扩展性?

问题描述

我需要制作一个用于选择数组筛选器的表格,需满足特定条件(例如不能同时选中client和user)。目前我通过为表格单元格设置ID实现了该功能,但当需要新增单元格时,现有代码扩展性差,难以维护,请问有没有更简洁的实现方案?

现有实现代码

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js"></script>
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" rel="stylesheet"/>

<style>
.blank_row { height: 50px !important; }
</style>

<table id="graphTable" class="table table-sm table-bordered">
  <thead>
    <tr>
      <th class="border" colspan="3">FILTER</th>
    </tr>
    <tr>
      <th>DATE</th>
      <th>CLIENT</th>
      <th>USER</th>
    </tr>
  </thead>
  <tbody>
    <tr class="blank_row">
      <td id="date"></td>
      <td id="client"></td>
      <td id="user"></td>
    </tr>
  </tbody>
</table>

<script>
jQuery(document).ready(function($) {
  filter = { date: 0, client: 0, user: 0 };
  $(".blank_row > td").click(function() {
    if (filter['date'] == 0 && $(this).attr('id') == 'date') {
      filter[$(this).attr('id')] = 1;
      $(this).addClass("bg-success");
    } else if (filter['date'] == 1 && $(this).attr('id') == 'date') {
      $(this).removeClass("bg-success");
      filter[$(this).attr('id')] = 0;
    }
    
    if (filter['client'] == 0 && filter['user'] == 0 && $(this).attr('id') != 'date') {
      filter[$(this).attr('id')] = 1;
      $(this).addClass("bg-success");
    } else if (filter['client'] == 1 || filter['user'] == 1) {
      $(this).removeClass("bg-success");
      filter[$(this).attr('id')] = 0;
    }
    
    console.log($(this).attr('id'));
    console.log(filter);
  });
});
</script>

优化方案

这是个很常见的扩展性问题,核心就是要把筛选规则和JS逻辑解耦,不用每次加新选项都改代码对吧?我给你一个基于**数据属性(data-*)**的方案,以后新增筛选器只需要在HTML里配置规则,JS完全不用动:

优化后的代码

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js"></script>
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" rel="stylesheet"/>

<style>
.blank_row { height: 50px !important; }
.filter-cell { cursor: pointer; } /* 加个鼠标指针提示可点击 */
</style>

<table id="graphTable" class="table table-sm table-bordered">
  <thead>
    <tr>
      <th class="border" colspan="4">FILTER</th> <!-- 新增了GROUP选项示例 -->
    </tr>
    <tr>
      <th>DATE</th>
      <th>CLIENT</th>
      <th>USER</th>
      <th>GROUP</th> <!-- 新增的筛选器 -->
    </tr>
  </thead>
  <tbody>
    <tr class="blank_row">
      <!-- 用data-filter-id替代id,data-mutual-group定义互斥组:同一组的选项不能同时选中 -->
      <td class="filter-cell" data-filter-id="date" data-mutual-group="none"></td>
      <td class="filter-cell" data-filter-id="client" data-mutual-group="client-user-group"></td>
      <td class="filter-cell" data-filter-id="user" data-mutual-group="client-user-group"></td>
      <td class="filter-cell" data-filter-id="group" data-mutual-group="client-user-group"></td> <!-- 和client、user互斥 -->
    </tr>
  </tbody>
</table>

<script>
jQuery(document).ready(function($) {
  // 自动从HTML读取所有筛选器,初始化状态,不用手动写每个选项
  const filterState = {};
  $('.filter-cell').each(function() {
    const filterId = $(this).data('filter-id');
    filterState[filterId] = 0;
  });

  $('.filter-cell').click(function() {
    const $cell = $(this);
    const filterId = $cell.data('filter-id');
    const mutualGroup = $cell.data('mutual-group');
    const isActive = filterState[filterId] === 1;

    if (isActive) {
      // 取消当前选中状态
      $cell.removeClass('bg-success');
      filterState[filterId] = 0;
    } else {
      // 先清空同一互斥组的所有选中状态
      if (mutualGroup !== 'none') {
        $(`.filter-cell[data-mutual-group="${mutualGroup}"]`).each(function() {
          const otherFilterId = $(this).data('filter-id');
          $(this).removeClass('bg-success');
          filterState[otherFilterId] = 0;
        });
      }
      // 选中当前单元格
      $cell.addClass('bg-success');
      filterState[filterId] = 1;
    }

    console.log('当前点击:', filterId);
    console.log('筛选状态:', filterState);
  });
});
</script>

方案优势

  • 高扩展性:新增筛选器时,只需在HTML里加一个<td>,配置data-filter-id和data-mutual-group(如果需要互斥),JS完全不用修改
  • 规则可视化:互斥规则直接写在HTML属性里,一眼就能看出哪些选项不能同时选中
  • 自动初始化:不用手动维护filter对象的初始值,JS会自动扫描所有筛选器并初始化状态
  • 灵活的互斥配置:可以把任意多个筛选器分到同一互斥组,比如示例里新增的GROUP选项,和CLIENT、USER自动实现三者互斥

内容的提问来源于stack exchange,提问作者rmarquet21

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 08:42:43