聊天应用搜索关键词高亮:替换文本为自定义HTML时转义异常如何解决?
问题根因
你出现多余转义的核心原因是使用了textContent赋值:textContent会将所有输入内容当成纯文本处理,你传入的<span>标签字符串会被自动转义为实体字符,自然无法作为HTML标签生效。
解决方案
不要直接修改文本节点的textContent,而是将匹配到关键词的文本节点拆分为三个部分替换原节点:
- 关键词之前的纯文本节点
- 带红色样式的
<span>元素,内容为匹配到的关键词 - 关键词之后的纯文本节点
这种方案既能实现标红效果,也不会引入XSS风险,所有原始文本内容都会被当成纯文本处理,只有你主动创建的<span>是HTML元素。
正确实现代码
const origin = "abc <div>all is text </div>"; // 转义后的安全文本 const searchKeyword = "div"; // 构建不区分大小写的正则,实际使用时注意转义关键词里的正则特殊字符 const reg = new RegExp(`(${searchKeyword})`, "gi"); const element = document.createElement("div"); element.innerHTML = origin; // 遍历所有子文本节点 const childNodes = [...element.childNodes]; for (let node of childNodes) { // 只处理文本节点,跳过其他元素节点 if (node.nodeType !== Node.TEXT_NODE) continue; const text = node.textContent; const fragments = text.split(reg); // 没有匹配到关键词直接跳过 if (fragments.length === 1) continue; // 构建新的节点片段替换原文本节点 const parent = node.parentNode; parent.removeChild(node); fragments.forEach(frag => { if (reg.test(frag)) { // 匹配到关键词,创建标红span const span = document.createElement("span"); span.style.color = "red"; span.textContent = "custom"; // 要展示原关键词直接赋值frag即可 parent.appendChild(span); } else if (frag) { // 普通文本创建文本节点插入 parent.appendChild(document.createTextNode(frag)); } }) } const result = element.innerHTML; console.log(result); // 输出结果:abc <<span style="color: red;">custom</span>>all is text </<span style="color: red;">custom</span>> // 完全符合预期效果
内容的提问来源于stack exchange,提问作者Phát Nguyễn
相关产品推荐
相关产品推荐

