如何用JavaScript或jQuery查找页面指定字符串并设置为粗体
页面文本字符串替换为加粗标签的实现方法
下面介绍几种用原生JavaScript和jQuery实现页面中指定字符串替换为<b>标签的方案,均能处理页面中任意文本元素、标题等多处匹配的场景:
原生JavaScript方案
1. 递归遍历文本节点(稳妥通用)
通过递归遍历DOM树中的所有文本节点,精准替换目标字符串,不会破坏原有DOM结构和事件绑定:
// 转义正则特殊字符的工具函数(可选,处理含特殊字符的目标字符串) function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); } function highlightText(targetStr) { const escapedStr = escapeRegExp(targetStr); const regex = new RegExp(`(${escapedStr})`, 'g'); // 递归遍历节点的内部函数 function traverse(node) { // 处理纯文本节点 if (node.nodeType === Node.TEXT_NODE) { const text = node.textContent; if (regex.test(text)) { const parts = text.split(regex); const parent = node.parentNode; parent.removeChild(node); parts.forEach(part => { if (part === targetStr) { const boldEl = document.createElement('b'); boldEl.textContent = part; parent.appendChild(boldEl); } else if (part) { // 跳过空字符串 parent.appendChild(document.createTextNode(part)); } }); } } // 处理元素节点,跳过脚本、样式标签避免误修改 else if (node.nodeType === Node.ELEMENT_NODE && !['SCRIPT', 'STYLE'].includes(node.tagName)) { Array.from(node.childNodes).forEach(traverse); } } // 从body开始遍历整个页面 traverse(document.body); } // 使用示例:替换页面中所有"ibf"为加粗样式 highlightText('ibf');
2. 用TreeWalker高效遍历(性能更优)
利用DOM API中的TreeWalker专门遍历目标节点,比递归遍历效率更高,适合大型页面:
function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); } function highlightWithTreeWalker(targetStr) { const escapedStr = escapeRegExp(targetStr); const regex = new RegExp(`(${escapedStr})`, 'g'); // 创建TreeWalker,过滤出需要处理的文本节点 const treeWalker = document.createTreeWalker( document.body, NodeFilter.SHOW_TEXT, { acceptNode: function(node) { // 跳过脚本、样式标签的文本,以及已被加粗的文本(避免重复处理) if (['SCRIPT', 'STYLE'].includes(node.parentNode.tagName) || node.parentNode.tagName === 'B') { return NodeFilter.FILTER_REJECT; } return regex.test(node.textContent) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP; } } ); // 先收集所有匹配的节点,避免DOM修改导致遍历异常 const targetNodes = []; let currentNode; while (currentNode = treeWalker.nextNode()) { targetNodes.push(currentNode); } // 批量处理节点 targetNodes.forEach(node => { const text = node.textContent; const parts = text.split(regex); const parent = node.parentNode; parent.removeChild(node); parts.forEach(part => { if (part === targetStr) { const boldEl = document.createElement('b'); boldEl.textContent = part; parent.appendChild(boldEl); } else if (part) { parent.appendChild(document.createTextNode(part)); } }); }); } // 使用示例 highlightWithTreeWalker('ibf');
jQuery方案
1. 递归扩展jQuery方法(稳妥兼容)
扩展jQuery的实例方法,递归处理元素内容,保留原有DOM结构和事件:
function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); } $.fn.highlightText = function(targetStr) { const escapedStr = escapeRegExp(targetStr); const regex = new RegExp(`(${escapedStr})`, 'g'); return this.contents().each(function() { if (this.nodeType === Node.TEXT_NODE) { const text = this.textContent; if (regex.test(text)) { const parts = text.split(regex); const $parent = $(this).parent(); $(this).remove(); $.each(parts, function(_, part) { if (part === targetStr) { $parent.append($('<b>').text(part)); } else if (part) { $parent.append(document.createTextNode(part)); } }); } } else if (this.nodeType === Node.ELEMENT_NODE && !$(this).is('script, style, b')) { $(this).highlightText(targetStr); } }); }; // 使用示例:对整个页面的文本进行处理 $('body').highlightText('ibf');
2. 直接替换innerHTML(简洁但有局限性)
这种方法更简洁,但仅适合没有子元素的文本节点,且会丢失元素上绑定的事件,需谨慎使用:
function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); } function highlightWithJQueryHTML(targetStr) { const escapedStr = escapeRegExp(targetStr); const regex = new RegExp(`(${escapedStr})`, 'g'); $('body *:not(script, style, b)').each(function() { const $el = $(this); // 仅处理无后代元素的文本节点 if ($el.children().length === 0 && regex.test($el.text())) { $el.html($el.text().replace(regex, '<b>$1</b>')); } }); } // 使用示例 highlightWithJQueryHTML('ibf');
注意事项
- 如果需要不区分大小写匹配,在创建正则表达式时添加
i标志,如new RegExp(..., 'gi') - 若目标字符串包含正则特殊字符(如
. * +等),必须用escapeRegExp函数转义,避免正则语法错误 - 所有方案均跳过了
<script>、<style>标签,防止误修改页面脚本和样式
内容的提问来源于stack exchange,提问作者Marvin Blach
相关产品推荐
相关产品推荐

