动态高亮需按场景区分技术方案:滚动用IntersectionObserver并缓存最顶部可见标题,关键词高亮须遍历文本节点并转义,Markdown需结构化转换后调用highlightElement,点击高亮需JS控制类名,且须预判深色模式、邮件客户端等边界问题。

动态高亮不是加个 <mark></mark> 或写个 :hover 就完事——它必须区分场景:是响应滚动、点击、搜索关键词,还是渲染 Markdown 代码?每种背后的技术路径和坑完全不同。
滚动时高亮对应导航项用 IntersectionObserver,别监听 scroll
监听 scroll 事件容易卡顿、判断不准,尤其在快速滚动或低性能设备上。用 IntersectionObserver 更轻量、更可靠:
- 配置
rootMargin: "0px 0px -50% 0px",让标题中点进入视口即触发,避免高亮滞后 - 必须缓存当前“最顶部且完全可见”的标题,而不是取第一个
isIntersecting === true的——否则滚动过快时会误判 - 首次加载要手动调用一次同步逻辑,否则初始位置可能没高亮
- 跳转后需重置观察器,否则动态插入的新标题不会被监听(如 SPA 路由切换)
关键词高亮必须遍历文本节点,不能碰 innerHTML
直接 el.innerHTML = el.innerHTML.replace(...) 是高危操作:
生成可在 deepbi 沙箱 iframe 内运行或作为独立文件运行的交互式 HTML 页面,使用 `window.deepbi` JS SDK 实现数据查询、空间管理、文件浏览及用户操作。当用户提出以下需求时启用该能力: - 创建 KPI 仪表盘、数据表格、文件浏览器、成员列表、管理页面; - 明确要求“转成 dhtml”、“转译成 HTML”、“把 XX 页面转成……”、“控制台页面”、“管理后台”、“DeepBI 页面迁移”; - 提及位于 `apps/console/src/featur
- 遇到
<script></script>或未闭合标签会撕裂 DOM,导致后续解析失败 - 正则不转义元字符(如用户搜
[a-z])直接报错中断 - HTML 特殊字符(
, <code>&)不转义可能执行 XSS - 正确做法是用
document.createTreeWalker(el, NodeFilter.SHOW_TEXT)只处理纯文本节点 - 多关键词要按长度降序匹配,否则
"JavaScript"和"Script"会嵌套错乱
Markdown 代码块高亮要先转结构再调用 hljs.highlightElement
hljs.highlightAll() 只扫描初始 DOM,对流式插入的
console.log(1)完全无感:
- 必须用正则提取三重反引号块,转换成标准
<pre class="brush:php;toolbar:false;"></pre> - 代码内容要 HTML 实体转义:
→ <code>,<code>&→& - 插入 DOM 后立即调用
hljs.highlightElement(codeEl),不要等下一帧 - 若用 SSE 流式输出,每次追加前先做转换,再高亮新插入的
<code>元素
点击持久高亮必须用 JS 控制类名,CSS :active 不够用
:active 只在鼠标按下瞬间生效,松开就还原,无法维持状态:
立即学习“前端免费学习笔记(深入)”;
- 需要持久态(如菜单选中、选项卡激活)必须用
element.classList.toggle("is-active") - 动态渲染的模板别重复绑定事件,改用事件委托监听父容器
- 移动端要同时监听
touchstart并preventDefault(),否则可能触发页面滚动 - 表单类控件(如
<input type="radio">)优先用:checked + label纯 CSS 方案,但前提是 HTML 结构合规
真正难的不是写出第一版效果,而是处理边界:深色模式下 <mark></mark> 文字消失、Outlook 邮件里样式被清空、高对比度系统强制重置背景、流式响应中途 abort 导致高亮残留……这些都得在方案设计阶段就预判。


















