用包裹语义单元,点击切换highlight类;仅存id列表至localstorage,加载后查找dom并校验存在性;移动端加touch-action: manipulation并设最小点击区44×44px;导出时按id提取textcontent及上下文生成纯文本或语义化html。

怎么用原生 HTML + CSS 实现可点击标注的阅读页
纯静态 HTML 本身不支持“高亮选中文本后保存标注”,但你可以用 contenteditable + document.execCommand(已废弃但仍有兼容性)或更现代的 Range + Selection API 模拟基础标注行为。实际项目中,推荐用 data-* 属性标记段落,配合 JS 绑定点击事件来切换标注状态——简单、可控、不依赖富文本编辑逻辑。
常见错误是直接对 <p></p> 加 onclick 然后改背景色,结果发现无法区分“段落内某句话”和“整段”,也存不了上下文。正确做法是把要标注的语义单元包裹进 <span></span>,并赋予唯一 id 或 data-note-id:
<p>这个<span data-note-id="n123" class="annotatable">关键结论</span>需要后续验证。</p>
- 标注触发用
click而非select:避免用户只是想复制文本时误触发 - 样式用
background-color: #ffeb3b+border-bottom: 1px dashed #ffc107更易识别,纯高亮在深色模式下会失效 - 不要用
!important锁死样式,留出 CSS 变量接口,比如--note-bg: #ffeb3b
localStorage 存标注状态时为什么只记 ID 不存 HTML 片段
因为存 HTML 片段(比如把整个 <span class="highlight">xxx</span> 写进 localStorage)会导致二次加载时结构错乱:原始 HTML 可能已被服务端动态修改,或 JS 注入了新节点,DOM 树对不上,innerHTML 替换会覆盖原有事件绑定甚至破坏语义。
只存 ["n123", "n456"] 这样的 ID 列表,页面加载完再遍历 DOM 找对应 data-note-id 元素并加类名,才是安全做法。
-
localStorage.setItem("notes", JSON.stringify(["n123", "n456"]))是标准写法 - 读取后必须做存在性检查:
if (el && el.nodeType === 1) { el.classList.add("highlight") },防止元素被移除后报错 - ID 建议用短哈希(如
crypto.randomUUID().slice(0,6))而非自增数字,避免多人协作时冲突
移动端点击标注区域响应慢或点不中的原因
不是 JS 性能问题,而是默认 touch-action: manipulation 缺失导致 iOS Safari 延迟约 300ms 才触发 click,且小范围 <span></span> 在手指触摸下容易误判为滑动。
- 给标注容器加
style="touch-action: manipulation",或全局 CSS:[data-note-id] { touch-action: manipulation; } - 确保可点击区域最小尺寸 ≥ 44×44px,可用
padding扩展点击热区,但不改变文字视觉范围 - 避免在
scroll中监听click,改用pointerdown+setTimeout防抖判断是否为点击(非长按/拖拽)
导出标注笔记时怎么避免把无关 DOM 一起打包
导出本质是序列化“用户真正关心的内容”,不是拷贝渲染后的 HTML。如果你把 document.body.innerHTML 直接当笔记内容,会混入导航栏、广告脚本、JS 注入的浮动按钮等。
正确路径是:从 localStorage 读出标注 ID 列表 → 用 document.querySelectorAll('[data-note-id]') 找到原始节点 → 提取 textContent 和上下文(比如父 <p></p> 的前 20 字 + 当前文本 + 后 20 字)→ 拼成 Markdown 风格片段。
- 不要用
outerHTML,它包含所有 class、style、内联事件,污染笔记纯度 - 上下文截取需防越界:
parentNode.textContent.slice(max(0, pos-20), pos+text.length+20) - 导出为 .txt 最稳妥;若需 .html,只用
<p></p>、<strong></strong>、<em></em>等语义标签,禁用<div> 和内联样式<p>最易被忽略的是:标注 ID 和原文本的耦合关系一旦被编辑器改动(比如用户删了一段话),ID 就失效了。没有服务端同步或 diff 算法,本地标注本质上是“快照式”的——这点必须提前告知用户。</p> </div>
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











