You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在含HTML代码与Base64图片的DOM文本中高亮搜索关键词?

解决方案:仅遍历文本节点实现关键词高亮

直接替换HTML字符串肯定会踩坑——要么改坏标签结构,要么把Base64图片里的字符也瞎替换。正确的思路是只找DOM里的纯文本节点处理,完全避开HTML标签、属性这些非用户可见的内容。

实现步骤

  1. 递归遍历目标DIV的所有节点,只挑纯文本节点(跳过元素、注释、属性节点)。
  2. 对每个文本节点用正则匹配关键词,把匹配到的内容套上带高亮样式的<span>。
  3. 把原文本节点拆分成“普通文本+高亮span+普通文本”的组合,替换回去。
  4. 加个清除高亮的函数,避免多次操作导致DOM乱套。

代码实现

高亮核心函数

function highlightKeyword(targetDiv, keyword) {
  // 先清掉之前的高亮,防止重复嵌套
  clearHighlight(targetDiv);
  
  if (!keyword.trim()) return;
  
  // 不区分大小写的全局匹配正则
  const regex = new RegExp(`(${keyword})`, 'gi');
  
  // 递归遍历节点
  function traverse(node) {
    // 跳过已经是高亮的span,避免死循环
    if (node.nodeType === Node.ELEMENT_NODE) {
      if (node.classList.contains('highlight-keyword')) return;
      for (let child of node.childNodes) {
        traverse(child);
      }
      return;
    }
    
    // 处理纯文本节点
    if (node.nodeType === Node.TEXT_NODE) {
      const text = node.textContent;
      if (!regex.test(text)) return;
      
      // 把文本拆成匹配和不匹配的片段
      const parts = text.split(regex);
      const parent = node.parentNode;
      
      // 删掉原文本节点
      parent.removeChild(node);
      
      // 逐个处理片段,生成新节点
      parts.forEach(part => {
        if (regex.test(part)) {
          const span = document.createElement('span');
          span.className = 'highlight-keyword';
          span.style.backgroundColor = 'yellow'; // 高亮样式可自定义
          span.textContent = part;
          parent.appendChild(span);
        } else if (part.trim()) {
          parent.appendChild(document.createTextNode(part));
        }
      });
    }
  }
  
  traverse(targetDiv);
}

清除高亮函数

function clearHighlight(targetDiv) {
  const highlights = targetDiv.querySelectorAll('.highlight-keyword');
  highlights.forEach(span => {
    // 把高亮span还原成文本节点
    const textNode = document.createTextNode(span.textContent);
    span.parentNode.replaceChild(textNode, span);
    // 合并相邻的文本节点,优化DOM结构
    mergeAdjacentTextNodes(span.parentNode);
  });
}

// 辅助函数:合并相邻文本节点
function mergeAdjacentTextNodes(node) {
  let currentNode = node.firstChild;
  while (currentNode) {
    const nextNode = currentNode.nextSibling;
    if (nextNode && currentNode.nodeType === Node.TEXT_NODE && nextNode.nodeType === Node.TEXT_NODE) {
      currentNode.textContent += nextNode.textContent;
      node.removeChild(nextNode);
    } else {
      currentNode = nextNode;
    }
  }
}

用例示范

<div id="content">
  <!-- 这里是你通过innerHTML插入的内容,包含标签和Base64图片 -->
  <a href="xxx">Link with 'a' in text</a>
  <p>Some text containing keywords like 'a' or 'blue'</p>
  <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==" alt="Base64图">
</div>
<button onclick="highlightKeyword(document.getElementById('content'), 'a')">高亮"a"</button>
<button onclick="clearHighlight(document.getElementById('content'))">清除高亮</button>

关键优势

  • 绝对不会碰HTML标签的尖括号内容、Base64属性值,完全不破坏原有页面结构。
  • 只处理用户能看到的文本内容,精准匹配高亮。
  • 样式可通过highlight-keyword类自由调整,不用改JS代码。

内容的提问来源于stack exchange,提问作者Roger Reyes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 06:35:24