需求背景:
1.输入的检索内容
2.显示共匹配多少个检索内容,当前显示的位置是在第几个匹配的检索内容
3.点击上一个图标可以找到上一条的匹配内容所在位置
4.点击下一个图标可以找到下一条的匹配内容所在位置
5.检索内容修改后,点击检索图标可对内容进行匹配检修
实现思路:
1.根据检索的关键词把文章中所有匹配的内容替换成<span class='highlight_Keyword'>关键词<span>
2.使用正则表达式查找所有带‘highlight_Keyword’的索引位置
3.在当前查找的索引替换成当前高亮的样式 “ highlight_Keyword highlight_yellow”
4.在css中设置好对应的样式就OK啦
先展示效果图:
用到的相关正则:
// 清除所有span标签
var reg1 = new RegExp('</?span.*?>', 'gi') //g 全局搜索 i表示不区分大小写
this.contextHtml = this.contextHtml.replace(reg1, '')
//搜索关键词,并返回所在位置(索引)
var rStr = new RegExp(value, 'gi') //i表示不区分大小写,g表示全局搜索
var arr = sText.match(rStr)
var a = -1
sText = sText.replace(rStr, function() {
a++
return '<span class="highlight_Keyword">' + arr[a] + '</span>'
})
放在component路径下作为组件使用,可以直接使用
<template>
<div class="keywords-search">
<div class="keywords-search-left">
<el-input
v-model="searchNodeInput"
placeholder="请输入节点名称"
clearable
@keyup.down.native="inputDown"
@keyup.up.native="inputUp"
@keyup.enter.native="inputDown"
/>
<div>
<span class="m-r-10">{{ nowNum }}/{{ totalNum }}</span>
<a
class="setting-secondary m-r-10"
href="javascript:void(0)"
:disabled="inputUpDisable"
@click="inputUp"
>
<i class="fa fa-caret-up" />
</a>
<a
class="setting-secondary m-r-10"
href="javascript:void(0)"
:disabled="inputDownDisable"
@click="inputDown"
>
<i class="fa fa-caret-down" />
</a>
<a
class="setting-primary"
href="javascript:void(0)"
@click="changeSearchNodeInput"
>
<i class="fa fa-search" />
</a>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'KeywordSearch',
props: {
searchNodeInput: { type: String }, // 父级输入框的值
context: { type: String } // 父级要搜索的内容
},
data() {
return {
contextHtml: null,
nowNum: 0,
totalNum: 0,
currentLabel: '',
currentNodeIndex: 0,
inputUpDisable: false,
inputDownDisable: false,
nodeSearchArr: []
}
},
watch: {
searchNodeInput(newVal, oldVal) {
if (oldVal) {
console.log('oldVal:', oldVal)
console.log('newVal:', newVal)
// const rStr = '<span class="highlight_Keyword">' + oldVal + '<\/span>'
// this.contextHtml = this.contextHtml.replaceAll(rStr, oldVal)
}
// 因为性能问题,暂时不使用值改变就搜索
// this.changeSearchNodeInput()
}
},
methods: {
// 上一个
inputUp() {
if (this.totalNum >= 1) {
this.inputUpDisable = false
if (this.currentNodeIndex === 0) {
this.currentNodeIndex = Number(this.totalNum) - 1
this.nowNum = String(this.currentNodeIndex + 1)
} else {
this.currentNodeIndex = this.currentNodeIndex - 1
this.nowNum = String(this.currentNodeIndex + 1)
}
this.findKeyword(this.currentNodeIndex)
} else {
// 这里向上的按钮要disable掉
this.inputUpDisable = true
}
},
// 下一个
inputDown() {
if (this.totalNum >= 1) {
this.inputDownDisable = false
if (this.currentNodeIndex === this.totalNum - 1) {
this.currentNodeIndex = 0
this.nowNum = String(this.currentNodeIndex + 1)
} else {
this.currentNodeIndex = this.currentNodeIndex + 1
this.nowNum = String(this.currentNodeIndex + 1)
}
this.findKeyword(this.currentNodeIndex)
} else {
// 这里向下的按钮要disable掉
this.inputDownDisable = true
}
},
// 改变搜索框中的值
changeSearchNodeInput() {
if (!this.searchNodeInput) {
return
}
debugger
if (!this.contextHtml) {
this.contextHtml = this.context
} else {
// 清除所有span标签
var reg1 = new RegExp('</?span.*?>', 'gi') // 匹配传入的搜索值不区分大小写 i表示不区分大小写,g表示全局搜索
this.contextHtml = this.contextHtml.replace(reg1, '')
}
let sText = this.contextHtml
const value = this.searchNodeInput
var rStr = new RegExp(value, 'gi') // 匹配传入的搜索值不区分大小写 i表示不区分大小写,g表示全局搜索
var arr = sText.match(rStr)
var a = -1
sText = sText.replace(rStr, function() {
a++
return '<span class="highlight_Keyword">' + arr[a] + '</span>'
})
this.nodeSearchArr = this.searchSubStr(sText, 'highlight_Keyword')
this.totalNum = this.nodeSearchArr.length
if (this.totalNum >= 1) {
this.nowNum = '1'
this.currentNodeIndex = 0
this.inputUpDisable = false
this.inputDownDisable = false
} else {
this.nowNum = '0'
this.inputUpDisable = true
this.inputDownDisable = true
this.currentNodeIndex = -1
}
this.contextHtml = sText
this.findKeyword(this.currentNodeIndex)
},
findKeyword(index) {
if (index > -1) {
// 清空当前高亮
this.clearCurrentStyle()
this.contextHtml = this.replaceStr(
this.contextHtml,
this.nodeSearchArr[index],
' highlight_yellow'
)
}
this.$emit('highlightKeyword', {
context: this.contextHtml,
keyword: this.searchNodeInput
})
},
// 查找所有'highlight_Keyword'位置
searchSubStr(str, findStr) {
let res
const list = []
const reg = new RegExp(findStr, 'gi')
while ((res = reg.exec(str))) {
// 把highlight_Keyword结束位置加到数组中
list.push(res.index + findStr.length)
}
console.log(list) // [8, 11, 29, 37, 51, 64]
return list
},
// 指定位置插入字符串
replaceStr(str, index, char) {
return str.substring(0, index) + char + str.substring(index)
},
// 清空当前高亮
clearCurrentStyle() {
this.contextHtml = this.contextHtml.replaceAll(' highlight_yellow', '')
}
}
}
</script>