搜索文字高亮(兼容带标签的数据)

45 阅读2分钟

先用正则匹配出所有的html标签,拿到数据里所有的标签元素 arr

image.png

然后再用正则的exec方法拿到每个html元素的下标 indexArr

(正则中需带g来匹配全局,这样在搜索中就能在上次匹配的末尾继续匹配,使我们的坐标数组能按照顺序插入)

image.png

接着截取每个标签元素之间的纯文字,按顺序插入新数组 textArr

startTextIndex是作为每段纯文字的起始坐标,每截取一段后,startTextIndex就会根据上面获取到的标签的下标加上标签长度来更新

image.png

遍历上面获取到的纯文字数组,对其中符合高亮文字的数据添加高亮操作

image.png

将高亮后的文字数组与标签数组拼接

image.png

以下是完整代码

/**
 * @description 搜索高亮
 * @param {String} searchValue 搜索值
 * @param {String} searchData 被搜索数据
 * @param {String} styleData 高亮样式
 * @returns {String}
 * */
export const searchHighLight = (searchValue: string, searchData: string, styleData = "color: #f20639") => {
  if (searchValue.trim() == "" || searchData.trim() == "") return searchData

  const regex = /<\/?.+?>/gi //正则匹配所有html标签
  const arr = searchData.match(regex) || [] //所有符合条件的元素
  console.log(arr)
  const regExp = new RegExp(searchValue.toString(), "gi")
  const heightLightText = `<span style="${styleData}">${searchValue}</span>`
  let newContent = ""

  if (arr.length > 0) {
    const indexArr = [] as number[] //符合条件元素的下标
    //利用正则的exec方法来获取每个符合元素的下标
    for (let count = 1; ; count++) {
      const result = regex.exec(searchData)
      if (result) {
        indexArr.push(result.index)
      } else {
        break
      }
    }
    //截取每个下标之间的文字
    const textArr = [] as string[]
    let startTextIndex = 0
    indexArr.map((item, index) => {
      const textItem = searchData.slice(startTextIndex, item)
      textArr.push(textItem)
      startTextIndex = item + arr[index].length
      if (index + 1 == indexArr.length && startTextIndex < searchData.length) {
        textArr.push(searchData.slice(startTextIndex))
      }
    })
    console.log(textArr)

    //遍历上面得到的文组数组,对其中有符合高亮文字的数据进行高亮操作
    textArr.map((item, index) => {
      console.log(item.includes(searchValue))
      if (item.includes(searchValue)) {
        textArr[index] = item.replace(regExp, heightLightText)
      }
    })
    console.log(textArr)

    //将高亮后的文字数组与标签数组拼接
    textArr.map((item, index) => {
      if (arr[index]) {
        const pice = item + arr[index]
        newContent += pice
      } else {
        newContent += item
      }
    })
  } else {
    newContent = searchData.replace(regExp, heightLightText)
  }
  return newContent ? newContent : searchData
}

个人经验分享,能力一般,如有错误或更好的方法,欢迎各位大神指导,帮助小弟进步,谢谢啦!