摘要:到目前為止我們只實現了搜索功能,按更優的體驗來講,在搜索結果中,要優先把相連匹配的放在首位,如關鍵字,要把結果放到前面。
我們先看一下效果圖:
這是搜索關鍵字cfg時,會自動匹配到config方法
同樣,我們再看另一個例子
通過關鍵字bi會匹配到好幾個結果
這個和一些編輯器的搜索功能很像,比如sublime text,不需要知道關鍵字的完整拼寫,只需要知道其中的幾個字母即可。
那么這個功能在前端我們如何去實現呢?
不考慮性能的話,我們可以用正則簡單實現如下:
把關鍵字拆分,加入(.?),如cfg最終為 (.?)(c)(.?)(f)(.?)(g)(.*?),然后拿這個正則去測試要搜索的列表,把符合要求的選項給拿出來即可
考慮到要高亮結果,我們還要生成對應的替換表達式,最后的函數如下
var escapeRegExp = /[-#$^*()+[]{}|,.?s]/g; var KeyReg = (key) => { var src = ["(.*?)("]; var ks = key.split(""); if (ks.length) { while (ks.length) { src.push(ks.shift().replace(escapeRegExp, "$&"), ")(.*?)("); } src.pop(); } src.push(")(.*?)"); src = src.join(""); var reg = new RegExp(src, "i"); var replacer = []; var start = key.length; var begin = 1; while (start > 0) { start--; replacer.push("$", begin, "($", begin + 1, ")"); begin += 2; } replacer.push("$", begin); info = { regexp: reg, replacement: replacer.join("") }; return info; };
調用KeyReg把關鍵字傳入,拿返回值的regexp去檢測搜索的列表,把符合的保存下來即可。
到目前為止我們只實現了搜索功能,按更優的體驗來講,在搜索結果中,要優先把相連匹配的放在首位,如bi關鍵字,要把bind結果放到beginUpdate前面。第二個截圖是有優化的地方的。
要完成這個功能,我們使用KeyReg返回值中的replacement,用它進行檢測,把結果中長度最長的放前面即可,這塊代碼以后有時間再補充
2018.5.31
今天重構了下,增加了結果排序,完整的代碼及使用示例如下
let Searcher = (() => { let escapeRegExp = /[-#$^*()+[]{}|,.?s]/g; let escapeReg = reg => reg.replace(escapeRegExp, "$&"); //groupLeft 與 groupRight是對結果進一步處理所使用的分割符,可以修改 let groupLeft = "(", groupRight = ")"; let groupReg = new RegExp(escapeReg(groupRight + groupLeft), "g"); let groupExtractReg = new RegExp("(" + escapeReg(groupLeft) + "[sS]+?" + escapeReg(groupRight) + ")", "g"); //從str中找到最大的匹配長度 let findMax = (str, keyword) => { let max = 0; keyword = groupLeft + keyword + groupRight; str.replace(groupExtractReg, m => { //keyword完整的出現在str中,則優秀級最高,排前面 if (keyword == m) { max = Number.MAX_SAFE_INTEGER; } else if (m.length > max) {//找最大長度 max = m.length; } }); return max; }; let keyReg = key => { let src = ["(.*?)("]; let ks = key.split(""); if (ks.length) { while (ks.length) { src.push(escapeReg(ks.shift()), ")(.*?)("); } src.pop(); } src.push(")(.*?)"); src = src.join(""); let reg = new RegExp(src, "i"); let replacer = []; let start = key.length; let begin = 1; while (start > 0) { start--; replacer.push("$", begin, groupLeft + "$", begin + 1, groupRight); begin += 2; } replacer.push("$", begin); info = { regexp: reg, replacement: replacer.join("") }; return info; }; return { search(list, keyword) { //生成搜索正則 let kr = keyReg(keyword); let result = []; for (let e of list) { //如果匹配 if (kr.regexp.test(e)) { //把結果放入result數組中 result.push(e.replace(kr.regexp, kr.replacement) .replace(groupReg, "")); } } //對搜索結果進行排序 //1. 匹配關鍵字大小寫一致的優先級最高,比如搜索up, 結果中的[user-page,beginUpdate,update,endUpdate],update要排在最前面,因為大小寫匹配 //2. 匹配關鍵字長的排在前面 result = result.sort((a, b) => findMax(b, keyword) - findMax(a, keyword)); return result; } }; })(); //假設list是待搜索的列表 let list = ["config", "user-page", "bind", "render", "beginUpdate", "update", "endUpdate"]; //假設userInput是用戶輸入的關鍵字 let userInput = "up"; //獲取搜索的結果 console.log(Searcher.search(list, userInput)); //?["(up)date", "begin(Up)date", "end(Up)date", "(u)ser-(p)age"]
對搜索結果中的內容做進一步處理渲染出來即可,比如把 ( 替換成 把 ) 替換成顯示到頁面上就完成了高亮顯示
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/95928.html
摘要:主機接入新表格組件支持拖拽調整表頭列寬背景現狀客戶對于主機名稱的命名規則廠商地域可用區產品業務服務內網,名稱較長,無法在列表頁直觀展示,只能手動上去顯示全部。如有關于控制臺產品的前端及視覺優化建議也歡迎和我們部門同學反饋。2月份根據用戶反饋、用戶調研以及自身使用產品體驗,將主機列為重點體驗優化目標產品,主要針對如下業務場景進行了優化:主機創建頁可用區售罄地域切換優化主機列表頁主機接入新表格組...
閱讀 2983·2021-11-23 09:51
閱讀 2997·2021-11-02 14:46
閱讀 864·2021-11-02 14:45
閱讀 2739·2021-09-23 11:57
閱讀 2493·2021-09-23 11:22
閱讀 1924·2019-08-29 16:29
閱讀 740·2019-08-29 16:16
閱讀 937·2019-08-26 13:44