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

基于JavaScript实现HTML表格类Excel筛选的多值过滤问题咨询

问题根因
  • 你在遍历表格行收集列唯一值时,仅将每个值对应的第一行存入了arrayMap,没有关联该值对应的所有行
  • 执行过滤逻辑时,仅修改了arrayMap中存储的少量行的显隐状态,未覆盖所有匹配值的行
修改后的完整代码

JS代码

$(document).ready(function() {
  $("table th").click(function() {
    showFilterOption(this);
  });
});

// 改为存储 值->所有匹配行的数组
var valueToRowsMap = {};

function showFilterOption(thObject) {
  var filterGrid = $(thObject).find(".filter");

  if (filterGrid.is(":visible")) {
    filterGrid.hide();
    return;
  }

  $(".filter").hide();

  filterGrid.empty();
  var allSelected = true;
  filterGrid.append(
    '<div><input id="all" type="checkbox" style="width: 10% !important" checked>All</div>'
  );

  var $rows = $(thObject).parents("table").find("tr");
  var uniqueValues = [];
  valueToRowsMap = {};
  var colIndex = parseInt($(thObject).attr("index"));

  // 第一次遍历:收集每个值对应的所有行
  $rows.each(function(ind, ele) {
    if (ind > 0) {
      var currentTd = $(ele).children().eq(colIndex);
      var cellVal = currentTd.html();
      // 初始化该值的行数组
      if (!valueToRowsMap[cellVal]) {
        valueToRowsMap[cellVal] = [];
        uniqueValues.push(cellVal);
      }
      valueToRowsMap[cellVal].push(ele);
      // 判断当前值对应的行是否有隐藏的,用来设置全选状态
      if ($(ele).is(":hidden")) {
        allSelected = false;
      }
    }
  });

  // 渲染筛选选项
  uniqueValues.forEach(function(val) {
    var div = document.createElement("div");
    div.classList.add("grid-item");
    // 只要该值对应的行有可见的,就设为选中
    var hasVisible = valueToRowsMap[val].some(row => $(row).is(":visible"));
    var str = hasVisible ? "checked" : "";
    div.innerHTML = '<br><input type="checkbox" ' + str + " >" + val;
    // 把值存在元素上,后续过滤用
    $(div).data("cellValue", val);
    filterGrid.append(div);
  });

  if (!allSelected) {
    filterGrid.find("#all").removeAttr("checked");
  }

  filterGrid.append(
    '<div style="text-align: center"><input id="close" type="button" value="Close" style="width: 40%"/><input id="ok" type="button" value="Ok" style="width: 40%"/></div>'
  );
  filterGrid.show();

  var $closeBtn = filterGrid.find("#close");
  var $okBtn = filterGrid.find("#ok");
  var $checkElems = filterGrid.find("input[type='checkbox']");
  var $gridItems = filterGrid.find(".grid-item");
  var $all = filterGrid.find("#all");

  $closeBtn.click(function() {
    filterGrid.hide();
    return false;
  });

  $okBtn.click(function() {
    // 遍历所有筛选选项
    filterGrid.find(".grid-item").each(function(ind, ele) {
      var cellVal = $(ele).data("cellValue");
      var isChecked = $(ele).find("input").is(":checked");
      // 批量操作该值对应的所有行
      valueToRowsMap[cellVal].forEach(row => {
        if (isChecked) {
          $(row).show();
        } else {
          $(row).hide();
        }
      });
    });
    filterGrid.hide();
    return false;
  });

  $checkElems.click(function(event) {
    event.stopPropagation();
  });

  $gridItems.click(function(event) {
    var chk = $(this).find("input[type='checkbox']");
    $(chk).prop("checked", !$(chk).is(":checked"));
  });

  $all.change(function() {
    var chked = $(this).is(":checked");
    filterGrid.find(".grid-item [type='checkbox']").prop("checked", chked);
  });

  filterGrid.click(function(event) {
    event.stopPropagation();
  });

  return filterGrid;
}

CSS代码(无修改)

table {
  margin: 0 auto;
  margin-top: 20px;
  width: 100%;
  position: relative;
  overflow: auto;
  overflow-y: overlay;
}

th,
thead {
  position: sticky;
  top: 0;
  border: 1px solid #dddddd;
  background-color: #1f2d54;
  text-align: center;
  color: white;
  table-layout: fixed;
  word-break: break-word;
  height: 45px;
}

.filter {
  position: absolute;
  width: 20vw;
  height: 30vh;
  display: none;
  text-align: left;
  font-size: small;
  z-index: 9999;
  overflow: auto;
  background: #ffffff;
  color: #1f2d54;
  border: 1px solid #dddddd;
}

.filter input {
  margin: 5px !important;
  padding: 0 !important;
  width: 10%;
}

HTML代码(无修改)

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table style='padding: 8px;'>
  <tr>
    <th index=0>Email
      <div class="filter"></div>
    </th>
    <th index=1>Name
      <div class="filter"></div>
    </th>
    <th index=2>Level
      <div class="filter"></div>
    </th>
    <th index=3>Location
      <div class="filter"></div>
    </th>
  </tr>

  <tr>
    <td>Email 1</td>
    <td>Name 1</td>
    <td>Level 1</td>
    <td>Location 2</td>
  </tr>
  <tr>
    <td>Email 1</td>
    <td>Name 1</td>
    <td>Level 1</td>
    <td>Location 1</td>
  </tr>
  <tr>
    <td>Email 2</td>
    <td>Name 1</td>
    <td>Level 2</td>
    <td>Location 1</td>
  </tr>
  <tr>
    <td>Email 3</td>
    <td>Name 2</td>
    <td>Level 2</td>
    <td>Location 1</td>
  </tr>
  <tr>
    <td>Email 3</td>
    <td>Name 3</td>
    <td>Level 1</td>
    <td>Location 2</td>
  </tr>
  <tr>
    <td>Email 1</td>
    <td>Name 2</td>
    <td>Level 2</td>
    <td>Location 1</td>
  </tr>
</table>
核心改动说明
  • 将原存储单行的arrayMap改为valueToRowsMap,存储列值到所有匹配行数组的映射,确保每个值对应的所有行都能被关联到
  • 遍历行时先完成所有行的分组,再渲染筛选选项,避免漏存相同值的行
  • 点击确认执行过滤时,批量操作每个选中值对应的所有行,实现和Excel一致的筛选效果

内容的提问来源于stack exchange,提问作者Daniel H.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 08:36:04