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