输入文本时如何正确高亮十六进制代码?解决重复叠加问题
解决输入时十六进制代码重复高亮的问题
问题原因
你遇到的重复叠加问题,是因为每次keyup触发时,代码会把已经被<mark>包裹的十六进制代码再次匹配替换。比如第一次把#fff变成<mark>#fff</mark>,第二次会匹配这个标签里的#fff,直接嵌套成<mark><mark>#fff</mark></mark>,多次按键后就会无限叠加标签。
解决方案1:先清除旧高亮,再重新渲染
最简单的修复方式是每次处理前,先把已有的<mark>标签还原成原始文本,再重新匹配高亮:
$(".hwt-highlights").on("keyup", function() { // 第一步:清除已有的高亮,把<mark>标签还原成原始的十六进制文本 const originalContent = this.innerHTML.replace( /<mark style="background-color: #([a-fA-F0-9]+)">#\1<\/mark>/g, "#$1" ); // 第二步:重新匹配合法的十六进制颜色代码并高亮 const hexRegex = /#([a-fA-F0-9]{3,6})/g; // 只匹配3/6位的标准颜色十六进制 const highlightedContent = originalContent.replace( hexRegex, '<mark style="background-color: #$1">#$1</mark>' ); this.innerHTML = highlightedContent; });
优化说明:
- 正则改成
#([a-fA-F0-9]{3,6}),只匹配符合规范的3位或6位十六进制颜色代码,避免误匹配#123abcdef这类超长内容。 - 还原逻辑精准匹配之前生成的
<mark>标签,确保不会误删其他内容。
解决方案2:只处理纯文本节点(更稳妥)
如果页面里有其他自定义标签,方案1的正则还原可能有风险,可以选择直接遍历纯文本节点,只处理未被<mark>包裹的文本,从根源避免重复叠加:
$(".hwt-highlights").on("keyup", function() { const hexRegex = /#([a-fA-F0-9]{3,6})/g; // 递归遍历节点,只处理纯文本和非mark元素 function processNode(node) { if (node.nodeType === Node.TEXT_NODE) { const text = node.textContent; if (!hexRegex.test(text)) return; // 把文本拆分成「普通文本+十六进制代码」的片段 const fragments = text.split(hexRegex); const frag = document.createDocumentFragment(); fragments.forEach((part, index) => { if (index % 2 === 0) { // 偶数位是普通文本,直接创建文本节点 frag.appendChild(document.createTextNode(part)); } else { // 奇数位是匹配到的十六进制代码,创建mark标签 const mark = document.createElement("mark"); mark.style.backgroundColor = `#${part}`; mark.textContent = `#${part}`; frag.appendChild(mark); } }); // 用新的片段替换原文本节点 node.parentNode.replaceChild(frag, node); } else if (node.nodeType === Node.ELEMENT_NODE && node.tagName !== "MARK") { // 跳过mark标签,只处理其他元素的子节点 for (let i = 0; i < node.childNodes.length; i++) { processNode(node.childNodes[i]); i++; // 替换节点后,子节点列表长度变化,调整索引 } } } processNode(this); });
额外优化建议:
因为keyup事件会在每次按键时触发,频繁处理DOM可能影响性能,可以加个防抖函数,延迟100-200ms再执行高亮逻辑,避免连续按键时重复触发:
function debounce(func, delay = 150) { let timer; return function() { clearTimeout(timer); timer = setTimeout(() => func.apply(this, arguments), delay); }; } // 绑定防抖后的处理函数 $(".hwt-highlights").on("keyup", debounce(function() { // 这里放上面的高亮逻辑 }));
内容的提问来源于stack exchange,提问作者devi
相关产品推荐
相关产品推荐

