可以使用 Vue2 + vue-highlightjs + vue-scrollto 插件来实现类似于 Ctrl+F 的前端搜索。其中,vue-highlightjs 插件可以帮助我们高亮匹配的文本;vue-scrollto 插件可以帮助我们滚动到匹配的位置。

以下是一个简单的实现:

<template>
  <div>
    <input v-model='searchText' />
    <button @click='searchNext'>下一个</button>
    <button @click='searchPrev'>上一个</button>
    <p>共找到 {{ searchCount }} 条结果,当前第 {{ searchIndex }} 条</p>
    <div ref='searchContent'>
      <p v-for='(line, index) in content' :key='index' :class='{ highlighted: index === highlightIndex }'>
        {{ line }}
      </p>
    </div>
  </div>
</template>

<script>
import { highlightBlock } from 'highlight.js'
import VueScrollTo from 'vue-scrollto'

export default {
  data() {
    return {
      searchText: '',
      content: [
        'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
        'Nulla facilisi. Fusce eu ante nec sapien finibus vestibulum.',
        'Vestibulum lacinia diam quis ipsum bibendum, in malesuada nisl sodales.',
        'Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.',
        'Suspendisse id est vel orci cursus ultrices.',
        'Suspendisse vitae urna a nibh aliquet lacinia.',
        'Sed fringilla eros eu arcu auctor bibendum.',
        'Vivamus nec metus sed nulla tincidunt mollis.',
        'Donec nec ex eu felis scelerisque finibus nec a eros.',
      ],
      searchCount: 0,
      searchIndex: 0,
      highlightIndex: -1,
    }
  },
  methods: {
    searchNext() {
      const searchRegex = new RegExp(this.searchText, 'gi')
      const startIndex = this.highlightIndex + 1

      for (let i = startIndex; i < this.content.length; i++) {
        const match = this.content[i].match(searchRegex)
        if (match) {
          this.searchCount = match.length
          this.searchIndex++
          this.highlightIndex = i
          this.scrollToMatch()
          return
        }
      }

      // 没有找到匹配项,从头再找一遍
      this.searchIndex = 0
      this.searchCount = 0
      this.highlightIndex = -1
      this.searchNext()
    },
    searchPrev() {
      const searchRegex = new RegExp(this.searchText, 'gi')
      const startIndex = this.highlightIndex - 1

      for (let i = startIndex; i >= 0; i--) {
        const match = this.content[i].match(searchRegex)
        if (match) {
          this.searchCount = match.length
          this.searchIndex--
          this.highlightIndex = i
          this.scrollToMatch()
          return
        }
      }

      // 没有找到匹配项,从尾再找一遍
      this.searchIndex = this.searchCount - 1
      this.highlightIndex = this.content.length
      this.searchPrev()
    },
    scrollToMatch() {
      const searchContent = this.$refs.searchContent
      const highlightedLine = searchContent.getElementsByClassName('highlighted')[0]
      VueScrollTo.scrollTo(highlightedLine, 500, { offset: -50 })
    },
  },
  watch: {
    searchText() {
      const searchRegex = new RegExp(this.searchText, 'gi')
      let count = 0
      let index = 0

      for (let i = 0; i < this.content.length; i++) {
        const match = this.content[i].match(searchRegex)
        if (match) {
          count += match.length
          if (index === 0) {
            this.highlightIndex = i
          }
          index++
        }
      }

      this.searchCount = count
      this.searchIndex = index > 0 ? 1 : 0
    },
  },
}
</script>

<style>
.highlighted {
  background-color: yellow;
}
</style>

在上面的代码中,我们首先引入了 highlight.js 和 vue-scrollto 插件,并在组件中使用了 vue-highlightjs 插件的 `highlightBlock` 方法来高亮匹配的文本。

然后,我们定义了一些数据和方法:

  • `searchText`:搜索框中的文本
  • `content`:需要搜索的文本内容
  • `searchCount`:搜索结果的总数
  • `searchIndex`:当前搜索结果的索引
  • `highlightIndex`:当前高亮的文本行的索引
  • `searchNext`:查找下一个匹配的文本
  • `searchPrev`:查找上一个匹配的文本
  • `scrollToMatch`:滚动到当前高亮的文本行

在 `searchNext` 和 `searchPrev` 方法中,我们使用正则表达式来查找匹配的文本,并更新 `searchCount`、`searchIndex` 和 `highlightIndex` 等数据。如果没有找到匹配项,则从头或尾再找一遍。

在 `scrollToMatch` 方法中,我们使用 vue-scrollto 插件来滚动到当前高亮的文本行。

最后,在组件的 `watch` 中,我们使用正则表达式遍历所有文本行,统计匹配的总数和当前搜索结果的索引,并更新数据。

Vue2 前端搜索实现:类似 Ctrl+F 功能(向上/向下匹配、高亮、计数)

原文地址: https://www.cveoy.top/t/topic/naeO 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录