原生JS表格筛选失效:所有行均被隐藏的问题排查
表格筛选功能问题排查与修复
问题描述
尝试使用原生JavaScript实现表格筛选功能,通过搜索输入框根据内容过滤表格行,但目前无论搜索字符串是否匹配数据,所有表格行都会被隐藏。
原实现代码
JavaScript
function searchTable() { var input, filter, table, tr, tds, i, txt input = document.querySelector(".search-box") filter = input.value.toUpperCase() table = document.querySelector(".table-search") tr = table.querySelectorAll("tr") for (i = 0; i < tr.length; i++) { tds = Array.from(tr[i].getElementsByTagName("td")) if (tds.length) { tds.forEach(function(td) { txt = (td.textContent || td.innerText).toUpperCase() console.log(txt); if (!txt.includes(filter)) { console.log('hide') tr[i].classList.add("d-none") } else { console.log('show') tr[i].classList.remove("d-none") } }) } } }
CSS
.card-header { display: flex; align-items: center; } .search-box { border-color: #ccc !important; border-left: none; padding-left: 0; } .search-box:focus { box-shadow: none; } .btn-search { background: #fff !important; opacity: 1 !important; border-color: #ccc !important; border-right: none; padding-left: 10px; padding-right: 10px; } .table-heading { font-size: 1.25rem; font-weight: 700; margin: 0 15px 0 0; line-height: 1; } .table th { background: #f6f6f6; } .table > tbody > tr:nth-child(even of :not([class*="d-none"])) > td { background: #f6f6f6; } .sort-button { border-radius: 3px; background: #ccc; border: none; } .sort-button.active { background: #04aa6d; color: #fff; } .sort-button.desc { transform: rotateX(180deg); }
HTML
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.6.0/css/all.min.css" rel="stylesheet"/> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" /> <div class="container-fluid"> <div class="card overflow-hidden shadow-sm my-2"> <div class="card-header"> <h2 class="table-heading">Users</h2> <div class="input-group input-group-prepend ms-auto w-75"> <button class="btn btn-sm btn-search" type="button" disabled> <i class="fa-solid fa-magnifying-glass"></i> </button> <input type="search" class="form-control form-control-sm search-box" placeholder="Search" onkeyup="searchTable()" /> </div> </div> <div class="card-body p-0"> <table class="table table-search m-0"> <thead> <tr> <th>Firstname</th> <th>Lastname</th> <th>Age</th> </tr> </thead> <tbody> <tr> <td class="fname">Alan</td> <td class="lname">Green</td> <td class="age">24</td> </tr> <tr> <td class="fname">Anne</td> <td class="lname">Smith</td> <td class="age">42</td> </tr> <tr> <td class="fname">Jane</td> <td class="lname">Doe</td> <td class="age">19</td> </tr> <tr> <td class="fname">July</td> <td class="lname">Dooley</td> <td class="age">121</td> </tr> <tr> <td class="fname">Mary</td> <td class="lname">Moe</td> <td class="age">21</td> </tr> </tbody> </table> </div> </div> </div>
问题根源
原代码的逻辑错误在于:遍历行内每个<td>时,只要有一个td不匹配搜索关键词,就会给整行添加隐藏类。比如某行有3个td,前两个匹配关键词,第三个不匹配,遍历到第三个td时就会把行隐藏,最终导致所有行都被隐藏——因为几乎没有行的所有td都能匹配任意搜索关键词。
修复方案
调整逻辑:对每一行先默认隐藏,只要找到任意一个匹配关键词的td,就将行设为显示,并且停止遍历该行的其他td,避免后续不匹配的td覆盖显示状态。同时优化遍历范围,只处理<tbody>内的行,跳过表头。
修复后的JavaScript代码
function searchTable() { const input = document.querySelector(".search-box"); const filter = input.value.toUpperCase(); const table = document.querySelector(".table-search"); // 只遍历tbody里的行,跳过表头 const rows = table.querySelectorAll("tbody tr"); rows.forEach(row => { // 默认隐藏行 row.classList.add("d-none"); const cells = row.getElementsByTagName("td"); // 遍历当前行的所有单元格 for (const cell of cells) { const text = (cell.textContent || cell.innerText).toUpperCase(); if (text.includes(filter)) { // 找到匹配项,显示行并跳出循环 row.classList.remove("d-none"); break; } } }); }
额外优化点
- 使用
const/let替代var,符合现代JS规范 - 直接遍历
<tbody>内的行,避免处理表头的<tr> - 找到匹配项后立即
break循环,减少不必要的遍历操作 - 简化变量声明,提升代码可读性
内容的提问来源于stack exchange,提问作者Razvan Zamfir
相关产品推荐
相关产品推荐

