以前我总是这样过滤搜寻内容

data.filter(item => item.indexOf(keywords) >= 0)

这样的确能够满足关键字搜寻需要,但鉴于前端是间接出现画面给用户的人,咱们总是须要站在用户的角度去思考问题。前面我的项目做多了,其实发现这样在用户体验上并不够敌对,咱们来看下上面这个例子:

chrome浏览器内编辑款式

vs code内编辑款式

在chrome浏览器内无奈进行非间断的字符匹配,造成了一些体验感的缺失,而在vs code内却能够自在间断地输出关键字匹配。毫无疑问在vs code中咱们的编辑体验会更加晦涩,因为在很多场景下,咱们记不得一段间断的关键字,而是在断断续续的关键字,此时咱们应用这种间断的关键字进行搜寻能够很好地进步用户体验,而且也不影响间断的关键字搜寻。

什么场景下能够用非间断关键字搜寻

这类需要个别为搜寻本地数据时,且需要场景没有明确指定须要间断的关键字搜寻时,咱们都能够应用非间断关键字搜寻来实现,具体列举了以下几个场景:

  1. 树形菜单项搜寻:相似治理后盾页面的菜单、多节点搜寻
  2. checkbox选项搜寻:选项较多的可搜寻checkbox内
  3. 门路列表搜寻:如vs code的文件搜寻
  4. 本地缓存搜寻:微信的缓存聊天记录关键字搜寻

接下来咱们探讨一下如何实现

得益于万能的npmjs.com,经验百般搜寻,我在下面找到了一个不错的js函数库实现了非间断关键字搜寻,咱们先看一个简略的Demo,再分析一下它的实现原理。

js库在此 -> string-discontinuous-match

此Demo中在1000条长度为200的随机字符串中非间断关键字搜寻,实现单次搜寻只须要1-2ms,性能可观。

接下来贴一下实现代码,通过Vue实现

<div id="app">  <div class="search-wrap">    <label></label>    <input class="search-box" v-model="val" @input="inputHandler" />  </div>  <div class="info">    <span>Data totals: {{ numbers }}</span>    <span v-if="performance">Performance: {{ performance }}</span>  </div>  <div class="result">    <span class="item" v-for="item in strings" :key="item" v-html="item"></span>  </div></div>
// 初始状态data() {  return {    val: '',    strings: strings,  // strings内蕴含1000条测试随机字符串    numbers: strings.length,    performance: '',  };}

以下为input事件实现

<input @input="inputHandler" />import { discontinuousMatch, replaceMatchedString } from 'string-discontinuous-match';function inputHandler() {  // this.val为搜寻关键字  if (this.val) {    let s = performance.now();      let ret = discontinuousMatch(strings, this.val);      let e = performance.now();      this.strings = ret.map(item => {        // 辅助函数replaceMatchedString        return replaceMatchedString(item, chars => `<span class="keyword">${chars}</span>`);      });      this.performance = (e - s) + 'ms';    }    else {      this.data = strings;      this.strings = strings;      this.performance = '';    }    this.numbers = this.strings.length;  }

搜寻后果格局为:

[  {    value: 'xxx',   // 被搜寻的字符串    index: 0,       // 该项在数组中的索引        // 匹配的关键字索引地位,如[0, 2]示意value中下标为0-2(蕴含2)地位的字符,14示意下标为14的单个字符。    position: [[0, 2], [10, 12], 14, 17],    lastIndex: 17   // 最初一个匹配的索引  },  // ...]

所以你能够通过position信息去高亮对应地位的字符,但实际上你并不需要本人解决,string-discontinuous-match为咱们提供了一个辅助函数来解决它,例如在inputHandler函数中,你能够看到将匹配后果循环传入了replaceMatchedString函数中,它的作用是帮咱们提取匹配到的字符串,它依据position数组顺次触发回调,在 position: [[0, 2], [10, 12], 14, 17]中会别离提取下标0到2的字符串,并触发一次回调,在回调中你能够返回转化后的字符串例如用<span>标签包裹它,接下来再提取10到12的字符串并触发回调,以此类推共计触发4次回调,最初把转化后的字符串返回给咱们,这样咱们就能够很不便地实现匹配关键字的高亮状态了。

通过这样一顿操作,就曾经实现了非间断关键字搜寻的性能了。

性能怎么样???

大家应该都会有这样的疑难,数据量小还好,但对于大数据量的匹配,会不会很慢呢?毕竟是非间断的匹配呢!!!
这个问题,此js库给出了这样的答复:

在10000个5000位随机字符串中搜寻50位随机要害字符串,疏忽大小写,花了101ms,性能好是不错的。

结尾

对于一个前端来说,咱们还是应该把用户体验放在重要的地位,而这个搜寻就是其中的优化点之一,只须要简略一步操作,咱们就能够解决此问题,不晓得正在看文章的你感觉是否值得一试呢?如果对这个js库感兴趣的能够自行钻研源码,其实它也很简略。
明天就到此啦,如有什么问题能够给作者去提issue哦。对我的教程感到称心,请不要悭吝你手中的收费赞赞哦!!!