indexeddb.open() 创建数据库需通过版本升级触发建库建表,必须在onupgradeneeded中调用createobjectstore()并指定keypath或autoincrement,后续操作须新建readwrite事务,且需全面处理onerror/onabort/onblocked等兼容性问题。

如何用 indexedDB.open() 创建数据库并处理升级事件
IndexedDB 不是“创建即存在”,而是通过 indexedDB.open() 打开时触发升级流程才真正建库建表。如果数据库不存在,或版本号升高,会触发 onupgradeneeded 事件;否则只走 onsuccess。
关键点:必须在 onupgradeneeded 回调里调用 event.target.result.createObjectStore(),不能在 onsuccess 里操作对象仓库(此时事务尚未激活)。
-
indexedDB.open("mydb", 1)第二个参数是整数版本号,不是字符串,也不能为 0 - 首次打开或升级时,
event.oldVersion === 0,此时必须新建对象仓库;若从 v1 升到 v2,则oldVersion === 1,可新增索引或字段 - 升级事务中不能使用
readonly模式 ——onupgradeneeded的事务默认是versionchange,权限足够
为什么 createObjectStore() 必须传 keyPath 或设 autoIncrement: true
对象仓库必须明确主键机制,否则抛出 InvalidStateError: Failed to execute 'createObjectStore' on 'IDBDatabase'。
两种合法方式:
- 显式指定主键路径:
db.createObjectStore("users", { keyPath: "id" }),要求每条数据都有id字段且唯一 - 启用自增主键:
db.createObjectStore("logs", { autoIncrement: true }),插入时不传 key,系统自动分配数字 ID(从 1 开始) - 二者不能共存 —— 若设了
keyPath,再传autoIncrement: true会报错
写入数据前必须先获取 readwrite 事务,不能复用升级事务
onupgradeneeded 里的事务只在该回调期间有效,一退出就关闭。后续增删改查必须新开事务。
常见错误:在 onsuccess 回调里直接调用 db.transaction().objectStore().add(),但忘了指定模式:
- 默认事务模式是
readonly,对add()、put()、delete()都拒绝 —— 报错InvalidStateError: The transaction is not active或ReadOnlyError - 正确写法:
const tx = db.transaction("users", "readwrite"),第二个参数必须显式写"readwrite" - 事务生命周期很短,所有操作要在
tx.oncomplete或tx.onerror触发前完成,不能异步延迟执行
如何安全地处理 IndexedDB 的兼容性与拒绝承诺链
现代浏览器基本支持,但 Safari 在私密模式下会静默拒绝打开数据库(onblocked 不触发,onsuccess 也不触发),导致卡死;另外 Promise 化封装容易忽略错误分支。
- 务必监听
onblocked:当旧版本数据库被其他标签页占用时,新版本打不开,需提示用户关闭其他页面 - 不要只靠
onsuccess,onerror和onabort都要处理,尤其onerror可能包含UnknownError(如磁盘满) - 用 Promise 封装时,reject 应覆盖
onerror和onabort,而不仅仅是onsuccess的 resolve —— 否则失败时 Promise 永远 pending
最易被忽略的是:对象仓库名区分大小写,且一旦创建无法重命名;升级时若想改结构,只能新建 store + 迁移数据,没有 ALTER TABLE。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











