先用正则匹配出所有的html标签,拿到数据里所有的标签元素 arr
然后再用正则的exec方法拿到每个html元素的下标 indexArr
(正则中需带g来匹配全局,这样在搜索中就能在上次匹配的末尾继续匹配,使我们的坐标数组能按照顺序插入)
接着截取每个标签元素之间的纯文字,按顺序插入新数组 textArr
startTextIndex是作为每段纯文字的起始坐标,每截取一段后,startTextIndex就会根据上面获取到的标签的下标加上标签长度来更新
遍历上面获取到的纯文字数组,对其中符合高亮文字的数据添加高亮操作
将高亮后的文字数组与标签数组拼接
以下是完整代码
/**
* @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
}
个人经验分享,能力一般,如有错误或更好的方法,欢迎各位大神指导,帮助小弟进步,谢谢啦!