Skip to content

IndexedDB 本地结构化存储

IndexedDB 是浏览器内置的非关系型数据库,专为客户端存储大量结构化数据设计。

参考:

对比其它本地存储方式

存储方式生命周期存储容量与服务器交互数据类型主要应用场景
cookie可设置过期时间4KB每次HTTP请求自动携带字符串身份验证、会话管理
sessionStorage会话结束时清除5MB仅在客户端存储字符串页面间临时数据传递
localStorage永久存储,除非主动删除5MB仅在客户端存储字符串用户偏好设置、主题配置
IndexedDB永久存储,除非主动删除理论上无上限仅在客户端存储结构化数据大量结构化数据、离线应用

兼容

浏览器支持情况良好。

  • Chrome 25+
  • Firefox 16+
  • Safari 6.1+
  • Edge 12+
  • iOS Safari 6.1+
  • Android Browser 4.4+‌
js
if ("indexedDB" in window) {
  // 支持IndexedDB
}

核心概念

1. 数据库(Database) ‌
  • 每个源(域名)可创建多个数据库,但通常一个应用使用一个数据库。
  • 数据库通过名称和版本号唯一标识,版本升级需显式处理。
‌2. 对象存储(Object Store) ‌
  • 类似数据库的“表”,存储键值对数据。
  • 每个对象存储需定义主键(keyPath),支持自动生成主键(autoIncrement)。
  • 可创建多个索引(Index),用于快速查询非主键字段。
‌3. 事务(Transaction) ‌
  • 所有数据操作必须在事务中完成,确保原子性。
  • 事务模式:
    • readonly:只读,性能最佳。
    • readwrite:读写,可能触发版本升级。
    • versionchange:数据库结构变更(如创建/删除对象存储)。
‌4. 游标(Cursor) ‌
  • 用于遍历对象存储或索引中的数据,支持范围查询和条件过滤。

操作流程

1. 打开/创建数据库

js
const request = indexedDB.open('myDatabase', 1); // 名称 + 版本(每次结构变更如新增对象存储,需升级版本)

request.onerror = (event) => {
  console.error('数据库打开失败:', event.target.error);
};

request.onsuccess = (event) => {
  const db = event.target.result; // 获取数据库实例
  console.log('数据库已打开:', db.name);
};

2. 添加数据

js
const transaction = db.transaction('users', 'readwrite'); // 开启读写事务
const store = transaction.objectStore('users'); // 获取对象存储实例

const request = store.add({ name: 'Alice', email: 'test@qq.com' }); // 添加数据

request.onsuccess = () => console.log('数据添加成功');
request.onerror = (e) => console.error('添加失败:', e.target.error);

3. 读取数据

js
const transaction = db.transaction('users', 'readonly'); // 开启只读事务
const store = transaction.objectStore('users'); // 获取对象存储实例
store.keyPath = 'email'; // 设置主键字段为 email
const request = store.get('test@qq.com'); // 根据主键读取数据

request.onsuccess = (event) => {
  const user = event.target.result;
  if (user) {
    console.log('读取到用户:', user);
  } else {
    console.log('未找到用户');
  }
};

request.onerror = (e) => console.error('读取失败:', e.target.error);

4. 更新数据

js
const transaction = db.transaction('users', 'readwrite'); // 开启读写事务
const store = transaction.objectStore('users'); // 获取对象存储实例
store.keyPath = 'email'; // 设置主键字段为 email
const request = store.put({ name: 'Alice Updated', email: 'test@qq.com' }); // 更新数据

request.onsuccess = () => console.log('数据更新成功');
request.onerror = (e) => console.error('更新失败:', e.target.error);

5. 删除数据

js
const transaction = db.transaction('users', 'readwrite'); // 开启读写事务
const store = transaction.objectStore('users'); // 获取对象存储实例
store.keyPath = 'email'; // 设置主键字段为 email
const request = store.delete('test@qq.com'); // 按主键删除
request.onsuccess = () => console.log('数据删除成功');
request.onerror = (e) => console.error('删除失败:', e.target.error);

6. 遍历数据

js
const transaction = db.transaction('users', 'readonly'); // 开启只读事务
const store = transaction.objectStore('users'); // 获取对象存储实例
store.keyPath = 'email'; // 设置主键字段为 email
const request = store.openCursor(); // 打开游标

request.onsuccess = (event) => {
  const cursor = event.target.result;
  if (cursor) {
    console.log('遍历到用户:', cursor.value);
    cursor.continue(); // 继续遍历下一条数据
  } else {
    console.log('遍历完成');
  }
};

request.onerror = (e) => console.error('遍历失败:', e.target.error);

7. 关闭数据库

js
db.close(); // 关闭数据库连接

IndexedDB 的简化库 localForage

大多数场景使用不到 IndexedDB,因为它的 API 相对复杂,且性能不如 localStorage。

有些需要IndexedDB场景, 大概会顺手用localStorage 写个查询算法解决。

把indexedDB简单封装成"localStorage" 就是 localForage

  • localForage是一个JavaScript库,能够类似localStorage的存储。
  • 他是异步存储,可以优化你的web应用程序的离线体验,而且能存储多种类型的数据。
  • localForage有一个优雅的降级策略,如果浏览器不支持indexedDB或者WebSQL则使用localStorage。
  • 不支持复杂查询,只能通过遍历所有数据来实现。

1. 安装

bash
npm install localforage

2. 引入

js
import localForage from 'localforage';

3. 存储

js
// 1:存普通数据
localforage.setItem('somekey''some value').then(function (value) {
    // 当值被存储后,可执行其他操作
    console.log(value);
}).catch(function(err) {
    // 当出错时,此处代码运行
    console.log(err);
});
// 2:存一个数组
localforage.setItem('myarray', [12'three']).then(function(value) {
    // 如下输出 `1`
    console.log(value[0]);
}).catch(function(err) {
    // 当出错时,此处代码运行
    console.log(err);
});

4. 读取

js
// 1:读取普通数据
localforage.getItem('somekey').then(function(value) {
    // 如下输出 `some value`
    console.log(value);
}).catch(function(err) {
    // 当出错时,此处代码运行
    console.log(err);
});
// 2:读取数组
localforage.getItem('myarray').then(function(value) {
    // 如下输出 `1`
    console.log(value[0]);
}).catch(function(err) {
    // 当出错时,此处代码运行
    console.log(err);
});

其它库

Dexie.js
  • 功能丰富,支持索引、事务、批量操作等
  • 复杂数据管理、多表结构的应用
idb
  • 接近原生 IndexedDB API 的轻量封装
  • 对性能要求高,熟悉 IndexedDB 的项目

京ICP备2024093538号-1