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

如何扩展前端表格多筛选器的JavaScript逻辑?

多筛选器表格的可扩展筛选逻辑优化问题

我正在构建一个包含多个筛选器的表格,目前已实现两个可联动的筛选器,筛选值来自如下拉框所示的选择器(暂未加入“Org Type”筛选器):
下拉框示例1
下拉框示例2

以下是当前实现筛选的JavaScript代码:

function filterTable_all() {
        filter = []
        // get filter 1 values and push to array
        var input = document.getElementById("KCPWinner");
        var values = getSelectValues(input);
        filter.push(values.toString().toUpperCase().split(","));
        // get filter 2 values and push to array
        var input = document.getElementById("yearFounded");
        var values = getSelectValues(input);
        filter.push(values.toString().toUpperCase().split(","));
        // get table
        var table = document.getElementById("mytableID");
        var tr = table.getElementsByTagName("tr");
        // loop through rows for filtering
        for (var i = 1; i < tr.length; i++) {
            for (var j = 0; j < filter.length; j++) {
               // if both filters are selected
                if (filter[0] != "" && filter[1] != "") {
                    if (filter[0].includes(tr[i].children[5].textContent.toUpperCase().trim()) && filter[1].includes(tr[i].children[4].textContent.toUpperCase().trim())){
                    tr[i].style.display = "block";
                }
                
                } // if one filter is selected
                else if (filter[0] != "" && filter[1] == "") {
                    if (filter[0].includes(tr[i].children[5].textContent.toUpperCase().trim())){
                    tr[i].style.display = "block";
                }

                } // if the other filter is selected
                else if (filter[0] == "" && filter[1] != "") {
                    if (filter[1].includes(tr[i].children[4].textContent.toUpperCase().trim())) {
                        tr[i].style.display = "block";
                    }
                }
            }
        }
    }

当前逻辑仅支持两个筛选器,但新增筛选器会让if语句数量指数级增长,无法良好扩展。请问如何优化该筛选逻辑以实现可扩展性?

触发filterTable_all()函数的select按钮(基于Django渲染):

<select class="submarket" style="" onchange='filterTable_all()' multiple name="yearFounded" id="yearFounded">
              {% for year in filter_options.year_founded %}
                  {% if year|toStr in liveFilters.year_founded %}
                <option class="submarketText checkedClass" value="{{ year }}" selected>{{ year }}</option>
                  {% else %}
                <option class="submarketText" value="{{ year }}">{{ year }}</option>
                  {% endif %}
          {% endfor %}
          </select>

注:所有筛选逻辑均为前端JavaScript实现


优化方案

核心思路是把每个筛选器的规则抽象成配置对象,让筛选逻辑通用化,新增筛选器只需要添加配置,不用修改核心判断代码。

1. 定义筛选规则配置

先创建一个数组,每个元素对应一个筛选器的配置,包含筛选器ID、对应表格列的索引,以及匹配规则(这里默认用包含匹配):

// 筛选规则配置,新增筛选器只需要往这里加条目
const filterConfigs = [
  {
    filterId: "KCPWinner",
    columnIndex: 5,
    matchFn: (filterValues, cellValue) => filterValues.includes(cellValue)
  },
  {
    filterId: "yearFounded",
    columnIndex: 4,
    matchFn: (filterValues, cellValue) => filterValues.includes(cellValue)
  },
  // 新增Org Type筛选器时,直接加这一条
  // {
  //   filterId: "OrgType",
  //   columnIndex: 2, // 替换成对应列的实际索引
  //   matchFn: (filterValues, cellValue) => filterValues.includes(cellValue)
  // }
];

2. 重构筛选函数

把原来的硬编码逻辑改成基于配置的通用逻辑,逻辑更清晰且易于扩展:

// 封装获取多选下拉框选中值的工具函数
function getSelectValues(select) {
  return Array.from(select.selectedOptions).map(option => option.value.trim());
}

function filterTable_all() {
  // 1. 收集所有筛选器的选中值(空数组表示未筛选)
  const activeFilters = filterConfigs.map(config => {
    const selectElement = document.getElementById(config.filterId);
    const selectedValues = getSelectValues(selectElement);
    return selectedValues.length > 0 
      ? selectedValues.map(val => val.toUpperCase().trim()) 
      : [];
  });

  // 2. 获取表格行(跳过表头)
  const table = document.getElementById("mytableID");
  const rows = table.querySelectorAll("tr:not(:first-child)");

  // 3. 遍历每一行,判断是否符合所有筛选规则
  rows.forEach(row => {
    let isMatch = true;

    // 逐个校验筛选规则
    for (let i = 0; i < filterConfigs.length; i++) {
      const config = filterConfigs[i];
      const filterValues = activeFilters[i];
      const cellValue = row.children[config.columnIndex].textContent.toUpperCase().trim();

      // 如果当前筛选器有选中值,且单元格值不满足匹配规则,标记为不匹配
      if (filterValues.length > 0 && !config.matchFn(filterValues, cellValue)) {
        isMatch = false;
        break; // 只要有一个筛选不通过,直接跳出循环
      }
    }

    // 根据匹配结果控制行的显示
    row.style.display = isMatch ? "block" : "none";
  });
}

3. 新增筛选器的操作

当需要添加新的筛选器(比如Org Type)时,只需要做两件事:

  • 在filterConfigs数组中添加对应的配置条目,指定筛选器ID和对应表格列索引;
  • 新增对应的<select>元素(和现有yearFounded的Django渲染逻辑一致),确保ID和配置中的filterId完全匹配。

额外优化说明

  • 修复了原代码中filter变量未声明导致的全局变量问题;
  • 使用querySelectorAll替代getElementsByTagName,返回静态集合,避免遍历过程中DOM变化引发的异常;
  • 匹配函数可自定义:如果需要精确匹配,只需调整matchFn逻辑;如果需要范围匹配,也可以自定义判断规则;
  • 代码结构更清晰,后续维护和扩展成本极低。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 11:47:05