Skip to content

浏览器支持

Chrome 4+ · Firefox 4+ · Safari 8+ · Edge 12+ 所有现代浏览器均已支持,包括移动端。

概述

浏览器端本地存储方案有三条路:localStorageIndexedDB、以及 Cache API(配合 Service Worker)。其中 localStorage 只存字符串、容量小、同步阻塞;IndexedDB 则是一个完整的本地数据库。

IndexedDB 是浏览器内置的 NoSQL 数据库,可以在本地存储大量结构化数据,支持索引查询、事务、游标遍历,数据量可达数百 MB 甚至 GB 级别(取决于磁盘空间)。

简单说:你想在浏览器里存大量数据、离线可用、快速查询?IndexedDB 就是答案。

和 localStorage 的核心区别

localStorageIndexedDB
数据类型仅字符串任何可结构化克隆的值(含二进制)
容量~5MB数百 MB 至 GB 级
API 风格同步(阻塞主线程)异步(Promise / 事件)
查询能力无(只能按 key)支持索引、范围查询、游标
事务支持支持原子操作
适用场景小配置、用户偏好大量业务数据、离线存储

核心概念

IndexedDB 的数据模型分为四层:

1. 数据库(Database)

一个数据库可以包含多个对象仓库,类似 MySQL 的"数据库"概念:

js
// 打开数据库(如果不存在则自动创建)
const request = indexedDB.open('MyAppDB', 1);

2. 对象仓库(Object Store)

类似"表"的概念,但每条记录是一个对象(JavaScript Object):

js
// 在 versionchange 事务中创建
db.createObjectStore('users', { keyPath: 'id' });
db.createObjectStore('notes', { keyPath: 'id', autoIncrement: true });

3. 索引(Index)

在对象仓库上建索引,可以按字段快速查询,类似数据库的索引:

js
const store = db.createObjectStore('users', { keyPath: 'id' });
store.createIndex('email', 'email', { unique: true });  // 按邮箱查
store.createIndex('age', 'age');                        // 按年龄查

4. 事务(Transaction)

所有读写操作必须在事务内进行,保证原子性:

js
const tx = db.transaction('users', 'readwrite');
const store = tx.objectStore('users');
store.add({ id: 1, name: 'Alice', email: 'alice@example.com' });

快速上手

js
// 打开数据库
const openDB = (name, version) =>
  new Promise((resolve, reject) => {
    const req = indexedDB.open(name, version);
    req.onupgradeneeded = (e) => {
      const db = e.target.result;
      if (!db.objectStoreNames.contains('notes')) {
        db.createObjectStore('notes', { keyPath: 'id', autoIncrement: true });
      }
    };
    req.onsuccess = (e) => resolve(e.target.result);
    req.onerror = () => reject(req.error);
  });

(async () => {
  const db = await openDB('DemoDB', 1);

  // 写
  const tx = db.transaction('notes', 'readwrite');
  await tx.objectStore('notes').add({ title: 'Hello', content: 'World' });

  // 读(按 key)
  const tx2 = db.transaction('notes', 'readonly');
  const req = tx2.objectStore('notes').get(1);
  req.onsuccess = () => console.log(req.result); // { id: 1, title: 'Hello', ... }
})();

注意事项

  • API 风格旧:IndexedDB 原生 API 用事件和请求对象,代码嵌套深;实际项目中建议用 idbDexie.js 封装库
  • 版本升级是同步的onupgradeneeded 回调里做 schema 变更,必须同步完成,不能异步等待
  • 事务不能跨数据库:一个事务只能操作同一个数据库里的对象仓库
  • 键类型:主键(keyPath)只能是字符串、日期、数字或 ArrayBuffer,不能是对象

基于 VitePress 构建