有时候给页面内容添加一个关键词搜索功能,如果搜索结果能够像浏览器搜索一样高亮显示,那找起来就会很明显体验会好很多。本文就介绍一下关键词搜索高亮的实现方案。
实现效果大概如下:

可在线预览:http://wintc.top/laboratory/#/search-highlight。
实现原理很简单:使用正则匹配出文本内容中的所有关键词,在关键词外包一层内联标签,比如span或者font,通过innerhtml渲染文本。使用css控制插入的内联元素样式,并且记录下当前搜索到的结果是第几个,使用不同的样式来展示。
比如文本内容是“实现江畔何人初见月?江月何年初照人?”,而关键词是“月”,那替换后的字符串可能变为:
江畔何人初见<font style="background: #ff9632">月</font>?江<font style="background: #ffff00">月</font>何年初照人?其中匹配的“月”被替换成了<font>月</font>,并且设置font标签的背景色,使得搜索到的第一个“月”(当前关键词)背景变为橘黄色,而第二个“月”背景变为黄色。
本文基于vue实现了一个组件,并且将组件发布到了npm上,如果你不想自己写组件,可以直接安装使用:vue-search-highlight。
接下来会介绍一下组件vue-search-highlight的使用,然后给出Vue中的搜索高亮的代码实现。
组件需要传入文本content以及关键词keyword,组件会渲染出一个包含content并且关键词被font元素替换的div元素。
组件功能如下:
使用方法:
// 如果使用yarn
yarn add vue-search-highlight
// 如果使用npm
npm add vue-search-highlightimport SearchHighlight from 'vue-search-highlight'
// 注册为子组件
components: {
  'search-highlight': SearchHighlight
},| props | 说明 | 备注 | 
| content | 需要展示的文本,搜索即在这个文本中进行。 | |
| keyword | 关键词 | |
| highlightStyle | 关键词高亮的CSS样式 | 非必传,参照浏览器搜索,默认设置背景为黄色#ffff00 | 
| currentStyle | 当前关键词高亮的CSS样式 | 非必传,参照浏览器搜索,默认设置背景为橘黄色#ff9632 | 
| 事件名 | 返回值 | 
| @current-change | 返回值:当前关键词索引。 关键词改变的时候,如果搜索到内容,会返回1,搜索不到则返回0。 | 
| @mactch-count-change | 返回值:文本匹配关键词总数。 | 
| 方法名 | 参数 | 说明 | 
| searchNext | 无 | 下一个关键词滚动到可视区域 | 
| searchLast | 无 | 上一个关键词滚动到可视区域 | 
| scrollTo | index | 滚动到第index(从1开始)个关键词 | 
使用示例:
<search-highlight
  class="search-highlight"
  ref="search"
  @current-change="currentChange"
  @mactch-count-change="matchCountChange"
  :content="content"
  :keyword="keyword">
</search-highlight>
<script>
import SearchHighlight from 'vue-search-highlight'
export default {
  components: {
    SearchHighlight
  },
  data () {
    return {
      currentIdx: 0,
      matchCount: 0,
      keyword: '月',
      content: `
            春江花月夜
                [唐] 张若虚
      春江潮水连海平,海上明月共潮生。
      滟滟随波千万里,何处春江无月明!
      江流宛转绕芳甸,月照花林皆似霰;
      空里流霜不觉飞,汀上白沙看不见。
      江天一色无纤尘,皎皎空中孤月轮。
      江畔何人初见月?江月何年初照人?
      人生代代无穷已,江月年年望相似。
      不知江月待何人,但见长江送流水。
      白云一片去悠悠,青枫浦上不胜愁。
      谁家今夜扁舟子?何处相思明月楼?
      可怜楼上月徘徊,应照离人妆镜台。
      玉户帘中卷不去,捣衣砧上拂还来。
      此时相望不相闻,愿逐月华流照君。
      鸿雁长飞光不度,鱼龙潜跃水成文。
      昨夜闲潭梦落花,可怜春半不还家。
      江水流春去欲尽,江潭落月复西斜。
      斜月沉沉藏海雾,碣石潇湘无限路。
      不知乘月几人归,落月摇情满江树。`,
    }
  },
  methods: {
    searchNext () {
      this.$refs.search.searchNext()
    },
    searchLast () {
      this.$refs.search.searchLast()
    },
    matchCountChange (count) {
      this.matchCount = count
    },
    currentChange (idx) {
      this.currentIdx = idx
    },
    checkKeydown (event) {
      if (event.shiftKey) {
        this.searchLast()
      } else {
        this.searchNext()
      }
    }
  }
}
</script>vue-search-highlight组件代码如下:
<template>
  <div class="search-highlight" v-html="contentShow">
  </div>
</template>
<script>
const CLASS_NAME = 'search-hightlight'
export default {
  props: {
    content: {
      type: String,
      default: ''
    },
    keyword: {
      type: String,
      default: ''
    },
    highlightStyle: {
      type: String,
      default: 'background: #ffff00'
    },
    currentStyle: {
      type: String,
      default: 'background: #ff9632'
    }
  },
  data () {
    return {
      lightIndex: 0,
      matchCount: 0
    }
  },
  computed: {
    contentShow () {
      if (!this.keyword) return this.content
      let reg = new RegExp(this.keyword, 'g')
      let stringList = this.content.split(reg)
      if (!stringList.length) return this.content
      let content = ''
      for (let i = 0; i < stringList.length - 1; i++) {
        let style = i === this.lightIndex ? this.currentStyle : this.highlightStyle
        content += `${stringList[i]}<fonttoken interpolation">${style}" ${CLASS_NAME}>${this.keyword}</font>`
      }
      content += stringList[stringList.length - 1]
      return content
    }
  },
  watch: {
    keyword: {
      immediate: true,
      handler () {
        this.lightIndex = 0
        this.getMatchCount()
      }
    },
    lightIndex: {
      immediate: true,
      handler () {
        this.$emit('current-change', this.lightIndex)
      }
    },
    matchCount: {
      immediate: true,
      handler () {
        this.$emit('mactch-count-change', this.matchCount)
      }
    }
  },
  methods: {
    scrollTo (index) {
      this.$nextTick(() => {
        let list = this.$el.querySelectorAll(`font[${CLASS_NAME}]`)
        if (list[index]) {
          this.lightIndex = index
          list[index].scrollIntoView()
        }
      })
    },
    searchNext () {
      this.$nextTick(() => {
        let idx = this.lightIndex >= this.matchCount - 1 ? 0 : this.lightIndex + 1
        this.scrollTo(idx)
      })
    },
    searchLast () {
      this.$nextTick(() => {
        let idx = this.lightIndex <= 0 ? this.matchCount - 1 : this.lightIndex - 1
        this.scrollTo(idx)
      })
    },
    getMatchCount () {
      this.$nextTick(() => {
        let list = this.$el.querySelectorAll(`font[${CLASS_NAME}]`)
        this.matchCount = list.length
      })
    },
  }
}
</script>原文:http://wintc.top/article/18
本文内容仅供个人学习/研究/参考使用,不构成任何决策建议或专业指导。分享/转载时请标明原文来源,同时请勿将内容用于商业售卖、虚假宣传等非学习用途哦~感谢您的理解与支持!
return从字面意思来看就是返回,官方定义return语句将终止当前函数并可以返回当前函数的值; 也就是说return后面可以跟一个value,也就是说可以跟javascript中的任何数据类型
JavaScript的一个常用特性是this关键字,但它也常常是该语言中最令人困惑和误解的特性之一。this到底是什么意思?它是如何决定的?本文试图澄清这种困惑,并以一种清晰的方式解释这个问题的答案。
了解自己,并且知道自己的价值所在,必须从页面自身信息价值的角度来优化,而不是从关键字角度来优化,做到专业、优质,能帮助用户解决某些问题。
JavaScript this 关键词指的是它所属的对象。它拥有不同的值,具体取决于它的使用位置:在方法中,this 指的是所有者对象。单独的情况下,this 指的是全局对象。
网站的推广从基础来讲,那就是关键词定位,说明白些就是给网站定位,网站的目的是什么,网站需要什么类的用户人群。有了这些需求才知道网站的关键词从什么方向来定位,那么,该如何给网站定位
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!