NoteZ_技术博客 NoteZ_技术博客
🏠 首页
  • 📚 Web技术
  • 📋 Npm笔记
  • 📑 Markdown
  • 📄 Git笔记
  • 📝 Nginx文档
  • 📓 Linux文档
  • 📖 技术文档
  • 📜 其他文档
  • 🧊 NodeJs
  • 🎡 Express
  • 🔥 Rust
  • 🎉 Koa2
  • 🍃 MongoDB
  • 🐬 MySql
  • 🥦 Oracle
  • 🍁 Python
  • 🍄 JavaScript
  • 🌰 CSS
  • 🧄 HTML
  • 🥑 Canvas
  • 🌽 Nuxt
  • 🍆 React
  • 🥜 Vue
  • 🧅 TypeScript
  • 🌶️ AI
  • 📘 分类
  • 📗 标签
  • 📙 归档
⚜️ 在线编辑 (opens new window)
  • 📁 站点收藏
  • 📦 前端组件库
  • 📊 数据可视化
  • 🌈 开源插件
  • 🎗️ 关于我
  • 🔗 友情链接
GitHub (opens new window)

NoteZ_技术博客

前端界的小学生
🏠 首页
  • 📚 Web技术
  • 📋 Npm笔记
  • 📑 Markdown
  • 📄 Git笔记
  • 📝 Nginx文档
  • 📓 Linux文档
  • 📖 技术文档
  • 📜 其他文档
  • 🧊 NodeJs
  • 🎡 Express
  • 🔥 Rust
  • 🎉 Koa2
  • 🍃 MongoDB
  • 🐬 MySql
  • 🥦 Oracle
  • 🍁 Python
  • 🍄 JavaScript
  • 🌰 CSS
  • 🧄 HTML
  • 🥑 Canvas
  • 🌽 Nuxt
  • 🍆 React
  • 🥜 Vue
  • 🧅 TypeScript
  • 🌶️ AI
  • 📘 分类
  • 📗 标签
  • 📙 归档
⚜️ 在线编辑 (opens new window)
  • 📁 站点收藏
  • 📦 前端组件库
  • 📊 数据可视化
  • 🌈 开源插件
  • 🎗️ 关于我
  • 🔗 友情链接
GitHub (opens new window)
  • JavaScript笔记

  • CSS笔记

  • HTML笔记

    • HTML字符串中匹配关键词高亮
      • 对纯文本字符串匹配
      • 对HTML字符串匹配
      • Vue文本关键字高亮插件
      • 参考链接
    • iframe加载完成事件
    • PC 端使用 rem 适配屏幕尺寸大小(自适应方案)
    • pc端网页屏幕自适应适配方案(rem)
    • 关于 HTML 中的 input accept属性详解(文件上传)
    • 前端如何使用a标签下载文件
    • 常用meta整理
    • 详解 input 中的 accept 属性(文件上传)
  • Canvas笔记

  • Nuxt笔记

  • React笔记

  • Vue笔记

  • TypeScript笔记

  • AI相关笔记

  • 开发文档
  • HTML笔记
NoteZ
2020-03-10
目录

HTML字符串中匹配关键词高亮

# 对纯文本字符串匹配

对于纯文本字符串使用正则加上class样式即可,

let text = '测试文本字符串';
let keyWord = '文本'; //匹配的关键词
let textHtml = text.replace(new RegExp(keyWord, 'gi'), `<span class="highlight">${keyWord}</span>`)
console.log(textHtml); // 输出:测试<span class="highlight">文本</span>字符串
1
2
3
4

# 对HTML字符串匹配

相关

// 深度优先遍历DOM树取出文本节点
function getTextNodeList (dom) {
  const nodeList = [...dom.childNodes]
  const textNodes = []
  while (nodeList.length) {
    const node = nodeList.shift()
    if (node.nodeType === node.TEXT_NODE) {
      textNodes.push(node)
    } else {
      nodeList.unshift(...node.childNodes)
    }
  }
  return textNodes
}
// 取出所有文本内容后续进行拼接
function getTextInfoList (textNodes) {
  let length = 0
  const textList = textNodes.map(text => {
    let start = length, end = length + text.wholeText.length
    length = end
    return [text.wholeText, start, end]
  })
  return textList
}
// 匹配关键词
function getMatchList (content, keyword) {
  const characters = [...'[]()?.+*^${}:'].reduce((r, c) => (r[c] = true, r), {})
  keyword = keyword.split('').map(s => characters[s] ? `\\${s}` : s).join('[\\s\\n]*')
  const reg = new RegExp(keyword, 'gmi')
  return [...content.matchAll(reg)] // matchAll结果是个迭代器,用扩展符展开得到数组
}

// 关键词使用font标签替换
function replaceMatchResult (textNodes, textList, matchList) {
  // 对于每一个匹配结果,可能分散在多个标签中,找出这些标签,截取匹配片段并用font标签替换出
  for (let i = matchList.length - 1; i >= 0; i--) {
    const match = matchList[i]
    const matchStart = match.index, matchEnd = matchStart + match[0].length // 匹配结果在拼接字符串中的起止索引
    // 遍历文本信息列表,查找匹配的文本节点
    for (let textIdx = 0; textIdx < textList.length; textIdx++) {
      const { text, startIdx, endIdx } = textList[textIdx] // 文本内容、文本在拼接串中开始、结束索引
      if (endIdx < matchStart) continue // 匹配的文本节点还在后面
      if (startIdx >= matchEnd) break // 匹配文本节点已经处理完了
      let textNode = textNodes[textIdx] // 这个节点中的部分或全部内容匹配到了关键词,将匹配部分截取出来进行替换
      const nodeMatchStartIdx = Math.max(0, matchStart - startIdx) // 匹配内容在文本节点内容中的开始索引
      const nodeMatchLength = Math.min(endIdx, matchEnd) - startIdx - nodeMatchStartIdx // 文本节点内容匹配关键词的长度
      if (nodeMatchStartIdx > 0) textNode = textNode.splitText(nodeMatchStartIdx) // textNode取后半部分
      if (nodeMatchLength < textNode.wholeText.length) textNode.splitText(nodeMatchLength)
      const font = document.createElement('font')
      font.innerText = text.substr(nodeMatchStartIdx, nodeMatchLength)
      textNode.parentNode.replaceChild(font, textNode)
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

完整代码调用

function replaceKeywords (htmlString, keyword) {
  if (!keyword) return htmlString
  const div = document.createElement('div')
  div.innerHTML = htmlString
  const textNodes = getTextNodeList(div)
  const textList = getTextInfoList(textNodes)
  const content = textList.map(({ text }) => text).join('')
  const matchList = getMatchList(content, keyword)
  replaceMatchResult(textNodes, textList, matchList)
  return div.innerHTML
}
1
2
3
4
5
6
7
8
9
10
11

# Vue文本关键字高亮插件

安装

npm install vue-search-highlight​
1

使用示例

<search-highlight
  class="search-highlight"
  ref="search"
  @current-change="currentChange"
  @match-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: `
            春江花月夜
                [唐] 张若虚
      春江潮水连海平,海上明<b>月</b>共潮生。
      滟滟随波千万里,何处春江无月明!
      江流宛转绕芳甸,月照花林皆似霰;
      空里流霜不觉飞,汀上白沙看不见。
      江天一色无纤尘,皎皎空中孤月轮。
      江畔何人初见月?江月何年初照人?
      人生代代无穷已,江月年年望相似。
      不知江月待何人,但见长江送流水。
      白云一片去悠悠,青枫浦上不胜愁。
      谁家今夜扁舟子?何处相思明<b>月</b>楼?
      可怜楼上月徘徊,应照离人妆镜台。
      玉户帘中卷不去,捣衣砧上拂还来。
      此时相望不相闻,愿逐月华流照君。
      鸿雁长飞光不度,鱼龙潜跃水成文。
      昨夜闲潭梦落花,可怜春半不还家。
      江水流春去欲尽,江潭落月复西斜。
      斜月沉沉藏海雾,碣石潇湘无限路。
      不知乘月几人归,落月摇情满江树。`,
    }
  },
  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>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67

# 参考链接

vue-search-highlight:https://github.com/Lushenggang/vue-search-highlight (opens new window)

#HTML
上次更新: 2024/11/25, 15:23:15
CSS实现左侧固定,右侧自适应方法
iframe加载完成事件

← CSS实现左侧固定,右侧自适应方法 iframe加载完成事件→

最近更新
01
Gitea数据备份与还原
03-10
02
Linux 中使用 rsync 同步文件目录教程
03-10
03
Linux 使用 rsync 互相传输同步文件的简单步骤
03-08
更多文章>
Theme by Vdoing | Copyright © 2019-2025 NoteZ,All rights reserved | 冀ICP备2021027292号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式