vue页面实现文本关键字检索,关键字高亮显示及定位功能
程序员文章站
2022-05-18 20:46:05
...
实现原理
- 将相应的关键字用标签包裹,添加相应的样式,
- 使用 dom.scrollIntoView() 方法实现定位功能
代码
- html部分
<template>
<div class="serach-box">
<el-input
placeholder="请输入关键字"
prefix-icon="el-icon-search"
v-model="inputLogValue"
clearable
size="small"
@keyup.enter.native='clickSearch'>
</el-input>
<el-button type="primary" size="small" icon="el-icon-search" @click="clickSearch"></el-button>
<div class="searchRight">
<span class="item" style='margin-right:5px'>{{curIndex}}/{{matchCount}}</span>
<el-tooltip class="item" effect="dark" content="上一个" placement="top">
<el-button @click="searchLast" icon="el-icon-arrow-up" circle type="text" size="mini" :disabled="matchCount==0"></el-button>
</el-tooltip>
<el-tooltip class="item" effect="dark" content="下一个" placement="top">
<el-button @click="searchNext" icon="el-icon-arrow-down" circle type="text" size="mini" :disabled="matchCount==0"></el-button>
</el-tooltip>
</div>
</div>
<div class="log_content" ref='log_content' v-if="searchStatus" v-html="contentShow"></div>
<template>
<style lang="scss" scoped>
.serach-box{
display: flex;
.el-input{
width: 300px;
.el-input__inner{
border-right: none;
}
}
.el-button{
border-radius: 0;
height: 32px;
box-sizing: border-box;
}
.searchRight{
height: 32px;
line-height: 32px;
padding: 0 10px;
background: #eee;
font-size: 14px;
color: #666;
.el-button+.el-button{
margin-left: 0;
}
}
}
.log_content{
width: 100%;
height: calc(100% - 40px);
line-height: 20px;
background-color: #333333;
color: #f0f0f0;
font-size: 13px;
overflow: overlay;
padding: 0 20px ;
overflow-x:hidden;
word-wrap: break-word;
white-space: pre-wrap;
box-sizing: border-box;
padding-bottom: 20px;
&::-webkit-scrollbar {
width: 10px;
height: 7px;
background-color: rgba(245, 245, 245, 0.1);
cursor: pointer;
z-index: 10;
}
&::-webkit-scrollbar-thumb {
height: 20px;
border-radius: 10px;
background-color: #dddee0;
cursor: pointer;
z-index: 10;
}
&::-webkit-scrollbar-thumb:hover {
cursor: pointer;
background-color: #c7c9cc;
}
}
</style>
- js部分
data() {
return {
logMessage:'',
inputLogValue:'',
lightIndex: 0,
curIndex:0,
matchCount: 0,
highlightStyle:'background: #ffff00;color:red;',
currentStyle:'background: #ff9632',
}
},
watch:{
inputLogValue: {
immediate: true,
handler (val) {
if(val==''){
this.lightIndex=0
this.curIndex=0
this.matchCount=0
this.searchStatus=0
}
}
},
},
methods:{
scrollTo (index) {
this.$nextTick(() => {
let list = this.$el.querySelectorAll(`.search-hightlight`)
if (list[index]) {
this.lightIndex = index
list[index].scrollIntoView()
}
})
},
searchNext () {
this.$nextTick(() => {
let idx
if(this.lightIndex >= this.matchCount-1){
this.lightIndex = 0
idx = 0
}else{
idx = this.lightIndex + 1
}
this.scrollTo(idx)
})
},
searchLast () {
this.$nextTick(() => {
let idx
if(this.lightIndex <= 0){
idx = this.matchCount - 1
this.lightIndex = this.matchCount - 1
}else{
idx = this.lightIndex - 1
}
this.scrollTo(idx)
})
},
getMatchCount () {
this.$nextTick(() => {
let list = this.$el.querySelectorAll(`.search-hightlight`)
this.matchCount = list.length
})
},
clickSearch(){
let reg = new RegExp(this.inputLogValue, 'ig')
let stringList = this.logMessage.split(reg)
if (stringList.length) {
this.searchStatus = 1
this.contentShow = ''
this.lightIndex = 0
for (let i = 0; i < stringList.length - 1; i++) {
let style = i === this.lightIndex ? this.currentStyle : this.highlightStyle
this.contentShow += `${stringList[i]}<font style="${style}" class='search-hightlight'>${this.inputLogValue}</font>`
}
this.contentShow += stringList[stringList.length - 1]
this.getMatchCount()
this.scrollTo(this.lightIndex)
}
},
}