关键词高亮不能只靠 font-weight: bold,因为纯样式无法区分搜索词与普通文本;必须用 javascript 将关键词包裹在语义化的 标签中,再通过 css 统一控制样式,并遍历文本节点安全替换以避免 dom 破坏和 xss。

关键词高亮为什么不能只靠 font-weight: bold
因为纯样式无法区分“搜索词”和“普通文本”,浏览器不知道哪部分该高亮。你得先用 JavaScript 把关键词包裹进特定标签(比如 <mark></mark>),再用 CSS 定义它的外观。直接对整行或整单元格加粗,会误伤非匹配内容,尤其当关键词是子串(如搜 “he” 匹配到 “the”)时更明显。
常见错误现象:innerHTML.replace(/keyword/g, '<strong>keyword</strong>') 看似可行,但没做 HTML 转义,如果表格数据本身含 或 <code>&,会破坏 DOM 结构;另外正则没加 g 和 i 标志,大小写不敏感和多处匹配就失效。
- 必须先对原始文本做
textContent提取,避免 XSS 和标签错乱 - 替换时用
RegExp构造函数,方便动态插入用户输入的关键词 - 包裹标签推荐用语义明确的
<mark></mark>,而非<span></span>—— 它原生支持可访问性(screen reader 会读作“marked text”)
<mark></mark> 的默认样式在不同浏览器里不一致
Chrome 默认给 <mark></mark> 加黄色背景,Firefox 是淡黄+圆角,Safari 则略暗且无圆角。如果你需要统一效果(比如深蓝底白字),必须显式重置所有关键属性:
mark {
background-color: #4a6fa5;
color: #fff;
padding: 0 3px;
border-radius: 2px;
font-weight: 600;
}
注意:mark 默认有内边距,但没 line-height 适配,若表格单元格用了 vertical-align: middle,高亮文字可能上下偏移。解决方案是加 line-height: 1.2 或设为 inherit;另外某些旧版 Edge 不支持 mark 伪元素,但作为语义标签它本身兼容性没问题(IE9+)。
表格中高亮要避开 <th>、<code><td> 以外的节点
<p>真实表格常含链接、图标、按钮等嵌套结构,比如:<code><td>@#@#@#@#@#@#@#@#@#@0</td>。如果直接对整个 <td> 的 <code>innerHTML 做替换,<a></a> 标签会被破坏。正确做法是遍历所有文本节点(nodeType === 3),只处理纯文本子节点:
- 用
table.querySelectorAll('td, th') 获取单元格
- 对每个单元格调用
node.childNodes,过滤出 TEXT_NODE
- 对每个文本节点内容执行关键词查找与替换,生成新
<mark></mark> 片段后用 replaceChild() 更新
- 跳过空文本节点和注释节点(
nodeType === 8)
性能问题:大数据量表格下高亮卡顿
table.querySelectorAll('td, th') 获取单元格node.childNodes,过滤出 TEXT_NODE
<mark></mark> 片段后用 replaceChild() 更新nodeType === 8)一个含 500 行 × 10 列的表格,逐个文本节点正则匹配 + DOM 替换,容易触发强制同步布局(layout thrashing)。优化点很实际:
- 关键词长度
- 用
String.prototype.indexOf()替代正则做首次定位,仅对命中位置再用slice()拆分并包裹 —— 避免反复编译正则 - 把高亮逻辑包装成
requestIdleCallback任务,防止阻塞主线程渲染 - 已高亮过的单元格加
data-highlighted="true"属性,下次搜索相同词时跳过
真正麻烦的是关键词含正则元字符(如 .、*、?),不转义就崩。所以 new RegExp(keyword.replace(/[.*+?^${}()|[]\]/g, '\$&'), 'gi') 这一行不能省——它看着琐碎,但漏掉就会让搜索 a.b 变成匹配任意字符。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











