基于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.
相关产品推荐
相关产品推荐

