實現(xiàn)html表格數(shù)據(jù)的模糊搜索,最常見方法是使用JavaScript進行dom操作,通過監(jiān)聽輸入事件實時篩選并顯示匹配行。1. 基本實現(xiàn):獲取用戶輸入,遍歷表格每一行和單元格,判斷內(nèi)容是否包含關(guān)鍵詞,動態(tài)設置行的顯示或隱藏;2. 性能優(yōu)化:對大數(shù)據(jù)量表格,采用節(jié)流/防抖機制延遲執(zhí)行搜索函數(shù),減少頻繁觸發(fā);3. 進階優(yōu)化:將表格數(shù)據(jù)提取到數(shù)組中,減少dom訪問頻率;4. 更智能的模糊搜索:引入編輯距離算法或使用fuse.JS等庫,提升匹配準確性和容錯能力;5. 后端搜索優(yōu)勢:適用于海量、敏感或需多用戶協(xié)作的場景,借助數(shù)據(jù)庫或全文搜索引擎(如elasticsearch)處理復雜查詢,減輕前端壓力,提高可擴展性與安全性。
實現(xiàn)HTML表格數(shù)據(jù)的模糊搜索,最常見且直接的方法是利用JavaScript在客戶端進行DOM操作,通過監(jiān)聽用戶輸入,實時篩選并顯示或隱藏表格行。這本質(zhì)上就是前端邏輯對頁面內(nèi)容的動態(tài)調(diào)整。
解決方案
說白了,核心思路就是拿到用戶的搜索詞,然后遍歷表格里的每一行(
比如,我們有一個簡單的HTML表格和搜索框:
立即學習“前端免費學習筆記(深入)”;
<input type="text" id="searchInput" onkeyup="searchTable()"> <table id="myTable"> <thead> <tr> <th>姓名</th> <th>城市</th> <th>職業(yè)</th> </tr> </thead> <tbody> <tr> <td>張三</td> <td>北京</td> <td>工程師</td> </tr> <tr> <td>李四</td> <td>上海</td> <td>設計師</td> </tr> <tr> <td>王五</td> <td>廣州</td> <td>產(chǎn)品經(jīng)理</td> </tr> <tr> <td>趙六</td> <td>北京</td> <td>銷售</td> </tr> </tbody> </table> <script> function searchTable() { let input, filter, table, tr, td, i, j, txtValue; input = document.getElementById("searchInput"); filter = input.value.toUpperCase(); // 轉(zhuǎn)換為大寫,方便不區(qū)分大小寫搜索 table = document.getElementById("myTable"); tr = table.getElementsByTagName("tr"); // 遍歷所有表格行,從索引1開始跳過表頭 for (i = 1; i < tr.length; i++) { let rowVisible = false; // 標記當前行是否應該顯示 // 遍歷當前行的所有單元格 td = tr[i].getElementsByTagName("td"); for (j = 0; j < td.length; j++) { if (td[j]) { txtValue = td[j].textContent || td[j].innerText; // 獲取單元格文本 if (txtValue.toUpperCase().indexOf(filter) > -1) { // 判斷是否包含搜索詞 rowVisible = true; break; // 找到一個匹配就夠了,跳出單元格循環(huán) } } } if (rowVisible) { tr[i].style.display = ""; // 顯示行 } else { tr[i].style.display = "none"; // 隱藏行 } } } </script>
這段代碼就是最基礎的實現(xiàn),它通過onkeyup事件監(jiān)聽用戶輸入,每次按鍵都重新過濾表格。
如何優(yōu)化大型HTML表格的模糊搜索性能?
當表格數(shù)據(jù)量比較大,比如幾百上千行的時候,每次按鍵都遍歷整個DOM樹進行搜索和修改樣式,用戶體驗可能會變差,頁面會顯得卡頓。所以,優(yōu)化是很有必要的。
我個人覺得,最直接有效的優(yōu)化方式是“節(jié)流”或“防抖”。說白了,就是不要用戶每敲一個鍵就立即執(zhí)行搜索,而是等用戶停下來或者在一定時間內(nèi)只執(zhí)行一次。比如,可以用setTimeout來延遲執(zhí)行搜索函數(shù),如果在延遲時間內(nèi)用戶又輸入了,就取消之前的延遲,重新計時。
let searchTimeout; function searchTableOptimized() { clearTimeout(searchTimeout); // 清除之前的延遲 searchTimeout = setTimeout(() => { // 這里放上面 searchTable() 函數(shù)里的所有邏輯 let input, filter, table, tr, td, i, j, txtValue; input = document.getElementById("searchInput"); filter = input.value.toUpperCase(); table = document.getElementById("myTable"); tr = table.getElementsByTagName("tr"); for (i = 1; i < tr.length; i++) { let rowVisible = false; td = tr[i].getElementsByTagName("td"); for (j = 0; j < td.length; j++) { if (td[j]) { txtValue = td[j].textContent || td[j].innerText; if (txtValue.toUpperCase().indexOf(filter) > -1) { rowVisible = true; break; } } } tr[i].style.display = rowVisible ? "" : "none"; } }, 300); // 延遲300毫秒執(zhí)行 } // 將 onkeyup="searchTable()" 改為 onkeyup="searchTableOptimized()"
另外,如果表格數(shù)據(jù)是固定的,可以在頁面加載時,把所有行的數(shù)據(jù)提前提取出來,存到一個JavaScript數(shù)組里。搜索的時候,就直接操作這個數(shù)組,找到匹配的行的索引,然后只對這些索引對應的DOM行進行顯示/隱藏操作。這樣可以避免每次都從DOM中讀取文本內(nèi)容,減少DOM操作次數(shù)。
對于更復雜的場景,一些成熟的JavaScript庫,比如DataTables.js或者List.js,它們內(nèi)部已經(jīng)做了大量的性能優(yōu)化,包括高效的DOM操作、虛擬滾動(只渲染可視區(qū)域的行)等,用起來會省心很多。它們通常提供更強大的搜索、排序和分頁功能。
除了簡單的包含匹配,還有哪些更“智能”的模糊搜索算法?
我們上面用的indexOf()或者includes()方法,只能實現(xiàn)精確的“包含”匹配。但有時候用戶可能會打錯字,或者希望搜索結(jié)果更“智能”一點,這時候就需要更高級的模糊匹配算法了。
一種常見的“智能”算法是基于編輯距離(Levenshtein distance)的匹配。它計算一個字符串轉(zhuǎn)換成另一個字符串所需的最少單字符編輯操作(插入、刪除、替換)次數(shù)。次數(shù)越少,說明兩個字符串越相似。你可以設置一個閾值,比如編輯距離小于等于2的都認為是匹配的。當然,計算編輯距離會比簡單的包含匹配消耗更多性能,所以需要權(quán)衡。
另一個我個人比較喜歡的方式是使用專門的模糊搜索庫,比如Fuse.js。它不僅僅是基于編輯距離,還會考慮字符的順序、位置、模式匹配等多種因素,給出更“人性化”的匹配結(jié)果。比如,搜索“北京”,它可能也能匹配到“京北”或者“北景”之類的,并給出一個相關(guān)性分數(shù)。
// 以Fuse.js為例 (需要引入Fuse.js庫) // npm install fuse.js 或者通過CDN引入 /* <script src="https://cdn.jsdelivr.net/npm/fuse.js/dist/fuse.min.js"></script> */ // 假設我們有一個數(shù)據(jù)數(shù)組,而不是直接從DOM讀取 const tableData = [ { name: '張三', city: '北京', occupation: '工程師' }, { name: '李四', city: '上海', occupation: '設計師' }, { name: '王五', city: '廣州', occupation: '產(chǎn)品經(jīng)理' }, { name: '趙六', city: '北京', occupation: '銷售' }, ]; // Fuse.js 配置 const options = { keys: ['name', 'city', 'occupation'], // 告訴Fuse在哪些字段里搜索 includeScore: true, // 是否包含匹配分數(shù) threshold: 0.4, // 匹配閾值,0表示完美匹配,1表示完全不匹配 }; const fuse = new Fuse(tableData, options); function searchTableFuzzy() { let input = document.getElementById("searchInput"); let query = input.value; let table = document.getElementById("myTable"); let tr = table.getElementsByTagName("tr"); if (query.trim() === '') { // 如果搜索框為空,顯示所有行 for (let i = 1; i < tr.length; i++) { tr[i].style.display = ""; } return; } const result = fuse.search(query); // 執(zhí)行模糊搜索 // 根據(jù)搜索結(jié)果顯示或隱藏行 const matchedIndices = new Set(result.map(item => tableData.indexOf(item.item))); for (let i = 1; i < tr.length; i++) { // 這里的 i-1 是因為 tr[0] 是表頭,而 tableData 是從0開始的 if (matchedIndices.has(i - 1)) { tr[i].style.display = ""; } else { tr[i].style.display = "none"; } } } // 將 onkeyup="searchTableOptimized()" 改為 onkeyup="searchTableFuzzy()"
這種方式需要先將表格數(shù)據(jù)轉(zhuǎn)換成JS對象數(shù)組,這在數(shù)據(jù)量大時,一次性提取和構(gòu)建索引的開銷是值得的。
在后端實現(xiàn)表格數(shù)據(jù)模糊搜索有什么優(yōu)勢和場景?
到目前為止,我們聊的都是客戶端的模糊搜索。但很多時候,尤其是數(shù)據(jù)量巨大(比如幾十萬、幾百萬甚至上億條記錄)或者需要多用戶實時協(xié)作的場景,純粹的客戶端搜索就不太現(xiàn)實了。這時候,后端搜索就成了唯一的選擇。
后端實現(xiàn)模糊搜索,最大的優(yōu)勢就是可伸縮性和處理復雜查詢的能力。所有的數(shù)據(jù)都存儲在數(shù)據(jù)庫里,搜索邏輯在服務器端執(zhí)行,客戶端只需要發(fā)送一個搜索請求,服務器返回過濾好的數(shù)據(jù)。
主要優(yōu)勢:
- 處理海量數(shù)據(jù): 數(shù)據(jù)庫天生就是為存儲和檢索大量數(shù)據(jù)而設計的。客戶端內(nèi)存和計算能力有限,不可能把所有數(shù)據(jù)都加載到瀏覽器里。
- 安全性: 數(shù)據(jù)不需要全部暴露給客戶端,只有符合條件的數(shù)據(jù)才會被發(fā)送過來。
- 復雜查詢: 數(shù)據(jù)庫查詢語言(sql)或者專業(yè)的搜索引擎(如Elasticsearch、solr)能處理比前端復雜得多的組合查詢、全文搜索、相關(guān)性排序等。
- 減輕客戶端負擔: 所有的計算都在服務器端完成,客戶端只負責展示,用戶體驗更流暢。
常見場景:
- 電商網(wǎng)站的商品搜索: 動輒百萬千萬的商品數(shù)據(jù),必須在后端進行高效搜索。
- 大型企業(yè)內(nèi)部系統(tǒng): 員工信息、客戶資料、項目文檔等,數(shù)據(jù)量龐大且敏感,需要后端權(quán)限控制和搜索。
- 日志分析平臺: 實時查詢和過濾海量的日志數(shù)據(jù)。
實現(xiàn)方式: 在后端,最常見的模糊搜索方式是利用數(shù)據(jù)庫的LIKE操作符,比如SQL中的select * FROM users WHERE name LIKE ‘%張%’;。但LIKE操作在數(shù)據(jù)量大時性能很差,尤其是在開頭使用通配符(%)時,因為它無法利用索引。
更高效的后端模糊搜索通常會使用專門的全文搜索引擎,如Elasticsearch、Solr,或者數(shù)據(jù)庫自帶的全文檢索功能(如postgresql的tsquery)。這些工具會提前對數(shù)據(jù)進行索引,構(gòu)建倒排索引等結(jié)構(gòu),使得模糊搜索和復雜查詢變得極其快速和高效。它們甚至能支持更高級的模糊匹配、同義詞、拼寫糾錯等功能。
所以,在做技術(shù)選型時,如果你的表格數(shù)據(jù)是動態(tài)加載的,并且數(shù)據(jù)量可能很大,那么后端搜索絕對是更穩(wěn)健、更可擴展的方案。客戶端搜索更適合靜態(tài)數(shù)據(jù),或者數(shù)據(jù)量可控的場景。