vue实用demo根据关键词查询文本,查询后显示关键词匹配总数与当前数,并在文本中高亮显示当前匹配的关键词,支持上一个下一个切换

查询文本demo说明

在这里插入图片描述

如上图,这个demo主要支持以下功能

  1. 在输入框中输入关键字,页面会根据关键字自动检索文本
  2. 完成检索后默认黄色高亮第一个匹配到的关键字,其余匹配到关键字灰色高亮,并展示出当前高亮关键词的序号和匹配到关键字的总数
  3. 通过上一个,下一个按钮或者up、down键盘,切换时黄色高亮新的关键字,更新当前关键词序号
  4. 下一个或上一个关键字没有在页面中,切换时自动调整滚动条,展示出下一个或上一个关键词
  5. 当前黄色高亮最后一个关键字,再点击下一个自动跳到文本第一个匹配的关键字;当前黄色高亮为第一个关键字,再点击上一个自动跳到文本最后一个匹配的关键字

关键实现步骤

  1. 利用正则表达式根据输入框输入的关键字将所有匹配到的关键字替换为灰色背景的span标签
    brightenKeyword () {
      this.allLightKeyWords = []
      const Reg = new RegExp(this.keyWordInput, 'ig')
      //将原文本匹配到的关键字全量替换为灰色背景的span标签
      /*
      .lightStyle{
		  color: #000;
		  background-color: #ccc;
	  }*/
      this.lightStr = this.oriTexts.replace(Reg, '<span class="lightStyle">' + this.keyWordInput + '</span>')
      this.allLightKeyWords = document.getElementsByClassName('lightStyle')
      //获取替换后所有的元素并返回
      return this.allLightKeyWords
    },
  1. 默认将匹配到第一个关键字黄色高亮,并定位匹配关键字在文本窗口中的位置
	async locationLightKeyWord () {
      await this.brightenKeyword()
      if (this.allLightKeyWords.length > 0) {
        this.$nextTick(function () {
          this.totalNum = this.allLightKeyWords.length
          // 输入框输入关键字时处理高亮和滚动
          this.allLightKeyWords['0'].className = 'lightStyle currentLightStyle'
          document.getElementById('textArea').scrollTop = this.allLightKeyWords['0'].offsetTop - 75
        })
      }
    },
  1. 处理上一个和下一个点击事件
  preKeyWord () {
      if (this.totalNum >= 1) {
        this.preBtnDisable = false
        if (this.currentNodeIndex === 0) {
          this.currentNodeIndex = this.totalNum - 1
          this.nowNum = this.currentNodeIndex + 1
        } else {
          this.currentNodeIndex = this.currentNodeIndex - 1
          this.nowNum = this.currentNodeIndex + 1
        }
        this.changeCurrentKeyword()
      } else {
        this.preBtnDisable = true
      }
    },

    nextKeyWord () {
      if (this.totalNum >= 1) {
        this.nextBtnDisable = false
        if (this.currentNodeIndex === this.totalNum - 1) {
          this.currentNodeIndex = 0
          this.nowNum = this.currentNodeIndex + 1
        } else {
          this.currentNodeIndex = this.currentNodeIndex + 1
          this.nowNum = this.currentNodeIndex + 1
        }
        this.changeCurrentKeyword()
      } else {
        this.nextBtnDisable = true
      }
    },
    //黄色高亮当前关键字
    changeCurrentKeyword () {
      // 给当前关键字添加黄色高亮的类
      this.allLightKeyWords[this.currentNodeIndex].className = 'lightStyle currentLightStyle'
      //点击下一个时将原来黄色高亮的关键字回复为灰色高亮
      if (this.allLightKeyWords[this.currentNodeIndex - 1]) {
        this.allLightKeyWords[this.currentNodeIndex - 1].className = 'lightStyle'
      }
      //点击上一个时将原来黄色高亮的关键字回复为灰色高亮
      if (this.allLightKeyWords[this.currentNodeIndex + 1]) {
        this.allLightKeyWords[this.currentNodeIndex + 1].className = 'lightStyle'
      }
	  // 调整窗口,使当前黄色高亮关键字在窗口的可视范围内
      document.getElementById('textArea').scrollTop = this.allLightKeyWords[this.currentNodeIndex].offsetTop - 75
    }

demo全量代码

以下为demo的全量代码,希望能帮助到你,如有不足随时欢迎大家交流沟通

<template>
  <div class="main-box">
    <el-col>
      <el-col :span="16">
        <el-input
          label-width="240px"
          placeholder="请输入关键字"
          prefix-icon="el-icon-search"
          v-model="keyWordInput"
          @input="keyWordChange"
          @keyup.down.native="nextKeyWord"
          @keyup.up.native="preKeyWord"
          @keyup.enter.native="nextKeyWord"
          clearable/>
      </el-col>
      <el-col :span="4" class="right-button">
        <span style="display:inline-block;width:20px">{{nowNum}}/{{totalNum}}</span>
        <el-tooltip effect="dark" content="上一个" placement="top">
          <el-button @click="preKeyWord" :disabled="preBtnDisable" icon="el-icon-arrow-up" circle type="text"></el-button>
        </el-tooltip>
        <el-tooltip effect="dark" content="下一个" placement="top">
          <el-button @click="nextKeyWord" :disabled="nextBtnDisable" icon="el-icon-arrow-down" circle type="text"></el-button>
        </el-tooltip>
      </el-col>
    </el-col>
    <el-col id="textArea"  class="scroller text-box" v-html="lightStr"></el-col>
  </div>
</template>
<script>
export default {
  name: 'test',
  data () {
    return {
      keyWordInput: '',
      lightStr: '',
      oriTexts: '',
      totalNum: 0,
      nowNum: 0,
      preBtnDisable: true,
      nextBtnDisable: true,
      currentNodeIndex: 0,
      allLightKeyWords: []
    }
  },
  watch: {

  },
  methods: {
    preKeyWord () {
      if (this.totalNum >= 1) {
        this.preBtnDisable = false
        if (this.currentNodeIndex === 0) {
          this.currentNodeIndex = this.totalNum - 1
          this.nowNum = this.currentNodeIndex + 1
        } else {
          this.currentNodeIndex = this.currentNodeIndex - 1
          this.nowNum = this.currentNodeIndex + 1
        }
        this.changeCurrentKeyword()
      } else {
        this.preBtnDisable = true
      }
    },

    nextKeyWord () {
      if (this.totalNum >= 1) {
        this.nextBtnDisable = false
        if (this.currentNodeIndex === this.totalNum - 1) {
          this.currentNodeIndex = 0
          this.nowNum = this.currentNodeIndex + 1
        } else {
          this.currentNodeIndex = this.currentNodeIndex + 1
          this.nowNum = this.currentNodeIndex + 1
        }
        this.changeCurrentKeyword()
      } else {
        this.nextBtnDisable = true
      }
    },

    keyWordChange (value) {
      this.keyWordInput = value
      this.currentNodeIndex = 0
      if (this.keyWordInput) {
        this.locationLightKeyWord()
        this.nowNum = 1
        this.preBtnDisable = false
        this.nextBtnDisable = false
      } else {
        this.nowNum = 0
        this.totalNum = 0
        this.preBtnDisable = true
        this.nextBtnDisable = true
        this.lightStr = this.oriTexts
      }
    },

    brightenKeyword () {
      this.allLightKeyWords = []
      const Reg = new RegExp(this.keyWordInput, 'ig')
      this.lightStr = this.oriTexts.replace(Reg, '<span class="lightStyle">' + this.keyWordInput + '</span>')
      this.allLightKeyWords = document.getElementsByClassName('lightStyle')
      return this.allLightKeyWords
    },

    async locationLightKeyWord () {
      await this.brightenKeyword()
      if (this.allLightKeyWords.length > 0) {
        this.$nextTick(function () {
          this.totalNum = this.allLightKeyWords.length
          // 输入框输入关键字时处理高亮和滚动
          this.allLightKeyWords['0'].className = 'lightStyle currentLightStyle'
          document.getElementById('textArea').scrollTop = this.allLightKeyWords['0'].offsetTop - 75
        })
      }
    },

    changeCurrentKeyword () {
      this.allLightKeyWords[this.currentNodeIndex].className = 'lightStyle currentLightStyle'
      if (this.allLightKeyWords[this.currentNodeIndex - 1]) {
        this.allLightKeyWords[this.currentNodeIndex - 1].className = 'lightStyle'
      }
      if (this.allLightKeyWords[this.currentNodeIndex + 1]) {
        this.allLightKeyWords[this.currentNodeIndex + 1].className = 'lightStyle'
      }

      document.getElementById('textArea').scrollTop = this.allLightKeyWords[this.currentNodeIndex].offsetTop - 75
    }
  },
  mounted () {
    this.lightStr = this.oriTexts = `测试文本99测试文本测试文本测试文本测试文
    本测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本
    测试文本测试文本测试文本测试文本测试文本测试文本1测试文本测试文本999测试文本测试文本测试文本测试文本测试文本
    测试文本测试文本测试文本测试文本测试文本2测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本
    测试文本测试文本测试文本测试文本3测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本
    测试文本测试文本测试文本4测试文本测试9999文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本
    测试文本测试文本5测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本
    测试文本6测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本
    测试文本测试文本测试文本测试文本测试文
    本测试文本测试文本测试99文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本
    测试文本测试文本测试文本测试文本测试文本测试文本1测试文本测试文本测试文本测试文本测试文本测试文本测试文本
    测试文本测试文本测试文本测试文本测试文本2测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本
    测试文本测试文本测试文本测试文本3测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本
    测试文本测试文本测试文本4测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本
    测试文本测试文本5测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本
    测试文本6测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本
    测试文本测试文本测试文本测试文本测试文
    本测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本
    测试文本测试文本测试文本测试文本测试文本测试文本1测试文本测试文本测试文本测试文本测试文本测试文本测试文本
    测试文本测试文本测试文本测试文本测试文本2测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本
    测试文本测试文本测试文本测试文本3测试文本测试文本测试文本测试99文本测试文本测试文本测试文本测试文本测试文本
    测试文本测试文本测试文本4测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本
    测试文本测试文本5测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本
    测试文本6测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本`
  }
}
</script>
<style>
.lightStyle{
  color: #000;
  background-color: #ccc;
}
.currentLightStyle{
  color: #000;
  background-color: #e6a23c;
}
.main-box{
  margin-top:20px;
  margin-left:50px;
  width:800px;
}
.right-button{
  float:right;
  margin-right:10px;
}
.text-box{
  margin-top:10px;
  height: 800px;
  width:760px;
  border:1px solid #c8c8c8;
  overflow-y:auto;
  padding:0px 6px;
  font-size:20px
}
.scroller::-webkit-scrollbar {
 width: 8px;
}
.scroller::-webkit-scrollbar-track {
 background-color:#F5F5F5;
 -webkit-border-radius: 2em;
 -moz-border-radius: 2em;
 border-radius:2em;
}
 .scroller::-webkit-scrollbar-thumb {
 background-color:#c8c8c8;
 -webkit-border-radius: 2em;
 -moz-border-radius: 2em;
 border-radius:2em;
}
</style>

补充

如果有朋友需要处理动态加载文本内容;请结合上一篇文章"vue实用demo通过滚动条滚动事件动态加载内容动态请求后台数据"

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值