目录
3.进阶版完整函数(word导入后或者有时候带了&#不可见字符转文字的情况下):
方法2:使用文本替换锚点后。使用range方法实现切换高亮。(防止数据太多。导致上下切换高亮卡顿)
1.替换&#不可见生成的字符(例如;等之类的)并替换掉标签。使所有关键词高亮。
关于方法2的知识点参考:http://t.csdn.cn/DT92m
方法1:使用纯正则替换
1.重点代码:
这边就是忽略标签直接匹配内容的部分,val为你搜索的内容文字
const reg = new RegExp(val, 'g')
this.detailLi.content = this.detailLi.content.replace(new RegExp('(?=\>).+?(?=\<)', 'g'), function (str) {
const reg1 = new RegExp('(?=>).+', 'g')
return str.replace(new RegExp('(>).+', 'g'), function (str2) {
return str2.replace(reg1, function (str1) {
return str1.replace(reg, '<em style="background-color: yellow">' + val + '</em>')
})
})
})
2.普通版完整函数(不带不可见字符&#情况):
test就是你搜索按钮点击事件,val既搜索框的内容
test (val, x) {
this.pickNum = 0
if (val !== '') {
if (this.searData !== '') {
this.detailLi.content = this.searData
} else {
this.searData = this.detailLi.content
}
const reg = new RegExp(String(val), 'g')
//正则校验除了标签之外
this.detailLi.content = this.detailLi.content.replace(new RegExp('(?=\>).+?(?=\<)', 'g'), function (str) {
const reg1 = new RegExp('(?=>).+', 'g')
return str.replace(new RegExp('(>).+', 'g'), function (str2) {
return str2.replace(reg1, function (str1) {
//这边是判断乱码过滤(连接数据库成功!)正则校验除了这种的之外
return str1.replace(new RegExp('^((?!(?=\&).+?(?=\;)).)*$','g'),function (str0) {
return str0.replace(reg, `<span id="test_idconese" style="background-color: #00a4ff">${val}</span>`)
})
})
})
})
const value2 = new RegExp('test_idconese', 'gi')
this.allData = this.detailLi.content.match(value2)
if (this.allData && this.allData.length > 0) {
this.allData.forEach((item, index) => {
this.detailLi.content = this.detailLi.content.replace('test_idconese', `test_${index}idconese`)
})
}
this.detailLi.content = this.detailLi.content.replace('<span id="test_0idconese" style="background-color: #00a4ff">', '<span id="test_0idconese" style="background-color: red">')
} else {
this.allData = []
}
if (x) {
if (this.searData !== '') {
this.detailLi.content = this.searData
} else {
this.searData = this.detailLi.content
}
}
},
3.进阶版完整函数(word导入后或者有时候带了&#不可见字符转文字的情况下):
test为完整函数:里面的decoders事件写在后面。
test (val, x, keyWord) {
const that = this
this.pickNum = 0
if (val !== '') {
if (this.searData !== '') {
this.detailLi.content = this.searData
} else {
this.searData = this.detailLi.content
}
const reg = new RegExp(val, 'g')
// 正则校验先乱码过滤(连接数据库成功!)正则校验除了这种的之外
this.detailLi.content = this.detailLi.content.replace(new RegExp('(?=\>).+?(?=\<)', 'g'), function (dades) {
if (dades.indexOf('&#') !== -1) {
return dades.replace(new RegExp('((?=\&).+?)(?=\;)+\;', 'g'), function (s) {
const tihuan = that.decoders(s)
return dades.replace(dades, `${tihuan}`)
})
} else {
return dades
}
})
// 正则校验除了标签之外
this.detailLi.content = this.detailLi.content.replace(new RegExp('(?=\>).+?(?=\<)', 'g'), function (str) {
const reg1 = new RegExp('(?=>).+', 'g')
return str.replace(new RegExp('(>).+', 'g'), function (str2) {
console.log(str2, 'str22')
return str2.replace(reg1, function (str1) {
console.log(str1.indexOf('&#'), str1, 'str2')
return str1.replace(reg, `<span id="test_idconese" style="background-color: #00a4ff">${val}</span>`)
// if (str1.indexOf('&#') !== -1) {
// return str1.replace(new RegExp('(?<=;)[^&]+(?=&)', 'g'), function (str0) {
// return str0.replace(reg, `<span id="test_idconese" style="background-color: #00a4ff">${val}</span>`)
// })
// } else {
// // 这边是判断乱码过滤(连接数据库成功!)正则校验除了这种的之外
// return str1.replace(new RegExp('^((?!((?=\&).+?)(?=\;)).)*$', 'g'), function (str0) {
// })
// }
})
})
})
const value2 = new RegExp('test_idconese', 'gi')
this.allData = this.detailLi.content.match(value2)
if (this.allData && this.allData.length > 0) {
this.allData.forEach((item, index) => {
this.detailLi.content = this.detailLi.content.replace('test_idconese', `test_${index}idconese`)
})
}
this.detailLi.content = this.detailLi.content.replace('<span id="test_0idconese" style="background-color: #00a4ff">', '<span id="test_0idconese" style="background-color: red">')
this.$nextTick(function () {
if (this.$el.querySelector('#test_0idconese')) {
this.$el.querySelector('#test_0idconese').scrollIntoView({
behavior: 'smooth',
inline: 'nearest',
})
}
})
} else {
this.allData = []
}
if (x) {
if (this.searData !== '') {
this.detailLi.content = this.searData
} else {
this.searData = this.detailLi.content
}
}
},
4.decoders函数:
&#特殊字符转文字的方法:
// &#编码转文字
decoders (str) {
var tempArr = str.split(/\&#|\;/)
console.log(str, tempArr, 'tem')
var tmpLength = tempArr.length
var str = ''
for (var i = 0; i < tmpLength; i++) {
if (tempArr[i] != '') {
str += String.fromCharCode(tempArr[i])
}
}
return str
},
5.锚点部分:
1.先对所有匹配的内容添加统一相同的ID:
return str1.replace(reg, `<span id="test_idconese" style="background-color: #00a4ff">${val}</span>`)
2.在通过match去获取有几个id为test_idconese的标签。并且遍历修改每个标签的ID添加index区别索引,用来后面锚点定位使用。
const value2 = new RegExp('test_idconese', 'gi')
this.allData = this.detailLi.content.match(value2)
if (this.allData && this.allData.length > 0) {
this.allData.forEach((item, index) => {
this.detailLi.content = this.detailLi.content.replace('test_idconese', `test_${index}idconese`)
})
}
6.锚点定位的使用:
这边的pickUp和pickDown就是ctrl+F中的下一个关键词和上一个关键词,我这边是自己写了个按钮点击事件去执行它,num写着玩的。没有用。
7.定位的主要代码在
根据id去定位到锚点所在位置。
this.$el.querySelector('#test_0idconese').scrollIntoView({
behavior: 'smooth',
inline: 'nearest',
})
8.锚点完整代码:
pickUp (num) {
if (this.pickNum > 0) {
this.pickNum = this.pickNum - 1
this.detailLi.content = this.detailLi.content.replace(`<span id="test_${this.pickNum}idconese" style="background-color: #00a4ff">`, `<span id="test_${this.pickNum}idconese" style="background-color: red">`)
this.detailLi.content = this.detailLi.content.replace(`<span id="test_${(this.pickNum + 1)}idconese" style="background-color: red">`, `<span id="test_${(this.pickNum + 1)}idconese" style="background-color: #00a4ff">`)
this.$el.querySelector(`#test_${this.pickNum}idconese`).scrollIntoView({
behavior: 'smooth',
inline: 'nearest',
})
} else if (this.pickNum === 0) {
this.$el.querySelector('#test_0idconese').scrollIntoView({
behavior: 'smooth',
inline: 'nearest',
})
}
},
pickDown (num) {
if (this.pickNum < this.allData.length - 1) {
this.pickNum = this.pickNum + 1
this.detailLi.content = this.detailLi.content.replace(`<span id="test_${this.pickNum}idconese" style="background-color: #00a4ff">`, `<span id="test_${this.pickNum}idconese" style="background-color: red">`)
this.detailLi.content = this.detailLi.content.replace(`<span id="test_${(this.pickNum - 1)}idconese" style="background-color: red">`, `<span id="test_${(this.pickNum - 1)}idconese" style="background-color: #00a4ff">`)
this.$el.querySelector(`#test_${this.pickNum}idconese`).scrollIntoView({
behavior: 'smooth',
inline: 'nearest',
})
} else if (this.pickNum === 0) {
this.$el.querySelector('#test_0idconese').scrollIntoView({
behavior: 'smooth',
inline: 'nearest',
})
}
},
方法2:使用文本替换锚点后。使用range方法实现切换高亮。(防止数据太多。导致上下切换高亮卡顿)
1.替换&#不可见生成的字符(例如🳃;等之类的)并替换掉标签。使所有关键词高亮。
test (val, x, keyWord) {
const that = this
this.pickNum = 0
if (val !== '') {
if (this.searData !== '') {
this.detailLi.content = this.searData
} else {
this.searData = this.detailLi.content
}
const reg = new RegExp(val, 'g')
// 正则校验先乱码过滤(连接数据库成功!)正则校验除了这种的之外
this.detailLi.content = this.detailLi.content.replace(new RegExp('(?=\>).+?(?=\<)', 'g'), function (dades) {
if (dades.indexOf('&#') !== -1) {
return dades.replace(new RegExp('((?=\&).+?)(?=\;)+\;', 'g'), function (s) {
const tihuan = that.decoders(s)
return dades.replace(dades, `${tihuan}`)
})
} else {
return dades
}
})
// 正则校验除了标签之外
this.detailLi.content = this.detailLi.content.replace(new RegExp('(?=\>).+?(?=\<)', 'g'), function (str) {
const reg1 = new RegExp('(?=>).+', 'g')
return str.replace(new RegExp('(>).+', 'g'), function (str2) {
return str2.replace(reg1, function (str1) {
return str1.replace(reg, `<span id="test_idconese" style="background-color: #00a4ff">${val}</span>`)
})
})
})
const value2 = new RegExp('test_idconese', 'gi')
this.allData = this.detailLi.content.match(value2)
if (this.allData && this.allData.length > 0) {
this.allData.forEach((item, index) => {
this.detailLi.content = this.detailLi.content.replace('test_idconese', `test_${index}idconese`)
})
}
//dom生成完毕后在执行的函数
this.$nextTick(function () {
if (this.$el.querySelector('#test_0idconese')) {
this.$el.querySelector('#test_0idconese').scrollIntoView({
behavior: 'smooth',
inline: 'nearest',
})
}
//高亮的方法
this.upGaGaLiang(val)
})
} else {
this.allData = []
}
//判断是否点击了关闭
if (x) {
if (this.searData !== '') {
this.detailLi.content = this.searData
} else {
this.searData = this.detailLi.content
}
}
},
2.高亮的方法函数(默认第一个高亮):
// 高亮
upGaGaLiang (val) {
this.range = document.createRange()
const container = document.getElementById('htmlcontent')
const allText = container?.innerText
this.inputValue = val
if (allText && allText.includes(this.inputValue)) {
// 获取所有节点
const containerAllNode = container.childNodes
// 用于保存找到的节点
this.findNode = []
for (let i = 0; i < containerAllNode.length; i++) {
// 遍历查询节点
if (containerAllNode[i].textContent?.includes(this.inputValue)) {
this.findNode.push(containerAllNode[i])
}
}
// 默认选中第一个
if (this.findNode && this.findNode.length > 0) {
const startNode = document.getElementById('test_0idconese').firstChild
if (startNode) {
this.range.setStart(startNode, 0)
this.range.setEnd(startNode, this.ritKeyWord.length)
const selection = window.getSelection()
selection?.removeAllRanges()
selection?.addRange(this.range)
}
// this.setSelect(0)
}
} else {
}
},
3.切换上一个和下一个(不卡顿)
pickUp (num) {
if (this.pickNum > 0) {
this.pickNum = this.pickNum - 1
if (document.getElementById((`test_${this.pickNum}idconese`))) {
const startNode = document.getElementById(`test_${this.pickNum}idconese`).firstChild
if (startNode) {
this.range.setStart(startNode, 0)
this.range.setEnd(startNode, this.ritKeyWord.length)
const selection = window.getSelection()
selection?.removeAllRanges()
selection?.addRange(this.range)
}
this.$el.querySelector(`#test_${this.pickNum}idconese`).scrollIntoView({
behavior: 'smooth',
inline: 'nearest',
})
}
} else if (this.pickNum === 0) {
if (document.getElementById('test_0idconese')) {
const startNode = document.getElementById('test_0idconese').firstChild
if (startNode) {
this.range.setStart(startNode, 0)
this.range.setEnd(startNode, this.ritKeyWord.length)
const selection = window.getSelection()
selection?.removeAllRanges()
selection?.addRange(this.range)
}
this.$el.querySelector('#test_0idconese').scrollIntoView({
behavior: 'smooth',
inline: 'nearest',
})
}
}
},
pickDown (num) {
if (this.pickNum < this.allData.length - 1) {
this.pickNum = this.pickNum + 1
if (document.getElementById(`test_${this.pickNum}idconese`)) {
const startNode = document.getElementById(`test_${this.pickNum}idconese`).firstChild
if (startNode) {
this.range.setStart(startNode, 0)
this.range.setEnd(startNode, this.ritKeyWord.length)
const selection = window.getSelection()
selection?.removeAllRanges()
selection?.addRange(this.range)
}
this.$el.querySelector(`#test_${this.pickNum}idconese`).scrollIntoView({
behavior: 'smooth',
inline: 'nearest',
})
}
} else {
if (this.allData.length && this.allData.length > 0) {
if (document.getElementById(`test_${(this.allData.length - 1)}idconese`)) {
const startNode = document.getElementById(`test_${(this.allData.length - 1)}idconese`).firstChild
if (startNode) {
this.range.setStart(startNode, 0)
this.range.setEnd(startNode, this.ritKeyWord.length)
const selection = window.getSelection()
selection?.removeAllRanges()
selection?.addRange(this.range)
}
}
}
}
},
文章内容大致为:通过v-html渲染的页面。
<div ref="htmlcontent" class="htmlcontent" id="htmlcontent" v-html="detailLi.content" />
data中的某些值:
data(){
return{
inputValue: '',
findNode: [],
index: -1,
range: null,
ritKeyWord:'',//搜索的关键词
}
}