10行JS实现字符串的关键词高亮

395 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第11天,点击查看活动详情

应用场景

在带有搜索逻辑的页面,我们经常需要在返回结果中,高亮出我们输入的搜索关键词。大多数时候,我们可以通过服务端进行分词切割,然后我们按照返回的数据进行展示即可。

但是如果有一天需要我们前端去实现类似的逻辑,尤其是开发任务比较紧张,或者实现的要求比较简单比如没有太多语义切割,仅仅是关键词和字符串的区别时,我们可以从前端的角度去尝试实现一下。

需求示例

  • 输入:输入的关键词为 “北京”
  • 搜索结果:北京市海淀区北京人民医院北京
  • 需求结果:将搜索结果中的“北京”2字高亮

需求分析

  • 忽略 UI 实现,忽略搜索结果实现
  • 仅考虑要将“北京”2个字从搜索结果中拆出来,即以北京为分割,将字符串分割为数组,方便业务逻辑使用即可

技术实现

let str = '北京市海淀区北京人民医院北京'
let key = '北京'

function splitStrByKey(str, key) {
    // 以 key 为匹配值,将字符串分割为数组,该数组中没有 key 值
    // 如果 key 在字符串开始,则数组会有一个 "" 空串在数组头部
    // 如果 key 在字符串结束,则数组会有一个 "" 空串在数组尾部
     let arr = str.split(key) 
     // flatMap 可以视为数组 arr 的 flat + map 组合
     // callback 表示数组每一个值都会遍历执行这个 callback ,并将返回结果汇集为一个临时数组 tmpArr
     // 如果 callback 中存在嵌套数组,则临时数组会进行 flat(1) 的操作,将该操作后的数据汇集为临时数组 tmpArr
     // 需要注意,此处的 flat 操作只会抹平 1 层
     // 当 arr 的每一个元素都执行了 callback 后,会将最终的 tmpArr 返回为 1 个新数组
    let rstArr = arr.flatMap((item, index) => {
        // 可以看做,每个匹配的数据都在数组的每个元素之前
        // 因此,每次遍历 arr 其实是在每个元素之前将原来的 [key, item] 放入了结果数组中
        // 需要注意,当 index === 0 时,不需要加入额外的 key , 否则会多加 1 个 key 值
        // 1) 当 key 值在最开始时,因为有 "" 在数组头部,所以不会在后续的 [key,item] 中,不会导致此时的 key 添加错误;
        // 2)当 key 值不在最开始时,因为数组头部为其他任意字符串,所以不需要在头部添加 key 值
         return index ? [key, item] : item 
    })
    // 需要去掉头部和尾部的 ”“ 字符串,以此纠正 key 值在头部和尾部时的异常场景
    let rst = rstArr.filter(Boolean)
    return rst;
}

var rst = splitStrByKey(str,key) // 输入 "北京市海淀区北京人民医院北京", 突出的字符串 "北京"
console.log(rst) // 输出 ['北京','市海淀区','北京','人民医院', '北京']

浏览知识共享许可协议

本作品采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可。