HTML5本身不解决冲突合并,真正起作用的是前端逻辑、IndexedDB存操作日志(含HLC时钟)、三路合并策略及Service Worker后台提交与冲突回传。

HTML5 本身不解决冲突合并,真正起作用的是前端逻辑、本地存储设计与后端协同机制。多端离线修改引发的冲突,核心在于“谁改了什么”和“怎么合才不丢内容”,不能靠 HTML 标签或属性自动处理。
用 IndexedDB 存操作日志,不是存最终结果
localStorage 容量小、无事务、无法结构化查询,不适合做同步基础。应使用 IndexedDB 建立 doc_edits objectStore,每条记录包含:
- docId:文档唯一标识(服务端下发)
- operation:操作类型(insert/update/delete/replace)
- content:变更内容(如富文本 delta、字段级 patch)
- hlc:混合逻辑时钟(含 wallTime + logicalCounter + clientId),用于判断因果关系
- status:pending / synced / conflicted
用户每次输入、删改、格式调整,都封装为一条原子操作写入 IndexedDB,而不是直接覆盖整个笔记内容。
靠 HLC 判断是否真冲突,而非简单比物理时间
仅用 Date.now() 比时间戳极易误判——设备时钟漂移几秒,就可能把手机上刚写的 500 字随笔,被笔记本上改了一个错别字的旧草稿覆盖掉。
混合逻辑时钟(HLC)结构示例:{ wallTime: 1728642120123, logicalCounter: 2, clientId: "phone-abc" }
它能准确识别两种情况:
- 版本 A → B:B 的 HLC 明确大于 A,说明是顺序更新,直接应用
- 版本 A 和 B:wallTime 相同但 clientId 不同,或 logicalCounter 无递进关系 → 并发冲突,需合并
三路合并代替“最后写入者胜”
拿到两个冲突版本(A 和 B)以及它们共同祖先版本(base),就能做字段级智能合并:
- 若 A 修改了标题,B 修改了正文 → 两者都保留
- 若 A 和 B 都改了同一段落 → 触发可视化差异对比界面,由用户确认或前端按语义规则自动取较新值
- 避免整条记录覆盖,只合并实际变动字段
这个过程在前端完成,不需要等待服务端响应,用户离线时也能看到合并预览。
Service Worker 负责后台提交与冲突回传
网络恢复后,Service Worker 的 sync 事件从 IndexedDB 中取出 pending 记录,按 HLC 排序逐条提交:
- 服务端接口需幂等,支持带 HLC 的乐观并发控制
- 若返回
conflict: true,将服务端最新内容 + 对应 HLC 写回 IndexedDB,并标记为 conflicted - 前端监听到该状态,弹出合并面板或自动尝试三路合并后重试
整个流程不依赖用户手动刷新,也不阻塞主页面交互。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











