如何在含HTML代码与Base64图片的DOM文本中高亮搜索关键词?
解决方案:仅遍历文本节点实现关键词高亮
直接替换HTML字符串肯定会踩坑——要么改坏标签结构,要么把Base64图片里的字符也瞎替换。正确的思路是只找DOM里的纯文本节点处理,完全避开HTML标签、属性这些非用户可见的内容。
实现步骤
- 递归遍历目标DIV的所有节点,只挑纯文本节点(跳过元素、注释、属性节点)。
- 对每个文本节点用正则匹配关键词,把匹配到的内容套上带高亮样式的
<span>。 - 把原文本节点拆分成“普通文本+高亮span+普通文本”的组合,替换回去。
- 加个清除高亮的函数,避免多次操作导致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
相关产品推荐
相关产品推荐

