IndexedDB 是浏览器端最成熟的离线存储方案,适合存富文本编辑器草稿;应结构化存储 content(白名单过滤 HTML)、selection(光标位置)、metadata(时间/版本等)和 editorState(工具栏状态),并用 Promise 封装 API、单库多表设计。

IndexedDB 是浏览器端最成熟的离线存储方案,适合存富文本编辑器的草稿(含 HTML、光标位置、样式状态等结构化数据)。关键不是“能不能存”,而是“怎么存得安全、可恢复、不丢内容”。
设计合理的草稿数据结构
不要直接存整个 contenteditable 的 innerHTML —— 它可能含临时标签、内联样式、跨域资源或 script 片段,既不安全也不利于后续解析。推荐结构化存储:
-
content:纯 HTML 字符串(经白名单过滤,如只保留
<p><h1><strong><em><ul><li>等) -
selection:记录光标/选区信息(如
{anchorNode: "p-2", anchorOffset: 12, focusNode: "p-2", focusOffset: 12}),用自定义 ID 标记节点而非 DOM 引用 -
metadata:标题、最后修改时间(
Date.now())、编辑器版本、是否已同步 - editorState:工具栏激活状态(如 bold=true, fontSize=14)、自定义插件数据(如表格行列数、代码块语言)
创建并打开数据库,定义对象存储
使用 Promise 封装 IndexedDB API,避免回调地狱。草稿库建议单库多表,例如:
function openDraftsDB() {
return new Promise((resolve, reject) => {
const request = indexedDB.open('EditorDrafts', 2);
request.onerror = () => reject(request.error);
request.onsuccess = () => resolve(request.result);
request.onupgradeneeded = (event) => {
const db = event.target.result;
// v1:基础草稿
if (!db.objectStoreNames.contains('drafts')) {
const store = db.createObjectStore('drafts', { keyPath: 'id' });
store.createIndex('updatedAt', 'updatedAt', { unique: false });
}
// v2:增加草稿版本历史(可选)
if (event.oldVersion < 2 && !db.objectStoreNames.contains('draftRevisions')) {
db.createObjectStore('draftRevisions', { keyPath: 'id' });
}
};
});
}
存草稿:自动节流 + 唯一键防覆盖
编辑过程中频繁保存易拖慢 UI,需节流(如 3 秒无操作再写入),且用唯一 ID 避免冲突:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
- 草稿 ID 推荐用 URL slug(如文档路径)或用户+文档标识组合(
user_abc123/article-intro) - 写入前先读取同 ID 草稿,比对
updatedAt时间戳,避免新内容被旧操作覆盖 - 使用
put()而非add(),确保更新而非报错 - 失败时降级:缓存到
localStorage并提示用户“已暂存本地,网络恢复后将自动同步”
读草稿 & 恢复编辑状态
页面加载时优先从 IndexedDB 加载最新草稿,再还原编辑器状态:
- 查询按
updatedAt降序,取第一条:index.openCursor(null, 'prev')或游标遍历 - 还原 HTML 时用
innerHTML赋值后,再调用restoreSelection()函数重建光标(根据 storedselection定位到对应节点和偏移) - 若草稿含图片 base64,注意 IndexedDB 存储限制(通常 50MB+,但需考虑低端设备),大图建议转为 blob URL 并单独存
URL.createObjectURL(blob)引用
不复杂但容易忽略:每次写入后监听 transaction.oncomplete 确保落盘成功;草稿清理逻辑要独立(如用户点击“清空草稿”才删库,而非每次关闭页面就清)。

















