js localstorage 和 indexeddb 用法

举报
林欣 发表于 2025/12/04 14:34:31 2025/12/04
【摘要】 在JavaScript中,localStorage 和 IndexedDB 是两种常用的客户端存储方案,分别适用于不同的场景。以下是它们的详细用法和对比: 1. localStorage 用法localStorage 是一个简单的键值对存储,数据以字符串形式保存,适合存储少量简单数据(如用户偏好、Token等)。 基本操作 存储数据// 存储字符串localStorage.setItem('...

在JavaScript中,localStorageIndexedDB 是两种常用的客户端存储方案,分别适用于不同的场景。以下是它们的详细用法和对比:


1. localStorage 用法

localStorage 是一个简单的键值对存储,数据以字符串形式保存,适合存储少量简单数据(如用户偏好、Token等)。

基本操作

存储数据

// 存储字符串
localStorage.setItem('username', 'JohnDoe');

// 存储对象(需序列化为JSON字符串)
const user = { name: 'Alice', age: 25 };
localStorage.setItem('user', JSON.stringify(user));

读取数据

const username = localStorage.getItem('username'); // "JohnDoe"
const userData = JSON.parse(localStorage.getItem('user')); // { name: 'Alice', age: 25 }

删除数据

localStorage.removeItem('username'); // 删除指定键
localStorage.clear(); // 清空所有数据

遍历所有键

for (let i = 0; i < localStorage.length; i++) {
  const key = localStorage.key(i);
  console.log(key, localStorage.getItem(key));
}

注意事项

  1. 仅支持字符串:存储对象需用 JSON.stringify(),读取时用 JSON.parse()
  2. 同步操作:所有操作会阻塞主线程,不适合存储大量数据。
  3. 存储上限:通常为 5MB(不同浏览器可能略有差异)。

2. IndexedDB 用法

IndexedDB 是一个事务型数据库,支持结构化数据存储(如对象、二进制数据),适合存储大量复杂数据(如应用状态、离线数据)。

基本操作

1. 打开数据库

const request = indexedDB.open('MyDatabase', 1); // 数据库名和版本号

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

request.onsuccess = (event) => {
  const db = event.target.result;
  console.log('数据库打开成功');
};

// 首次创建或升级数据库时触发
request.onupgradeneeded = (event) => {
  const db = event.target.result;
  
  // 创建对象存储空间(类似表)
  if (!db.objectStoreNames.contains('users')) {
    const store = db.createObjectStore('users', { keyPath: 'id' });
    // 可选:创建索引
    store.createIndex('name', 'name', { unique: false });
  }
};

2. 增删改查(CRUD)

(1)添加数据
function addUser(user) {
  const transaction = db.transaction(['users'], 'readwrite');
  const store = transaction.objectStore('users');
  const request = store.add(user);

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

addUser({ id: 1, name: 'Alice', age: 25 });
(2)查询数据
function getUser(id) {
  const transaction = db.transaction(['users'], 'readonly');
  const store = transaction.objectStore('users');
  const request = store.get(id);

  request.onsuccess = (e) => console.log('查询结果:', e.target.result);
  request.onerror = (e) => console.error('查询失败:', e.target.error);
}

getUser(1);
(3)更新数据
function updateUser(user) {
  const transaction = db.transaction(['users'], 'readwrite');
  const store = transaction.objectStore('users');
  const request = store.put(user); // put 会覆盖同名键的数据

  request.onsuccess = () => console.log('更新成功');
}

updateUser({ id: 1, name: 'Alice Updated', age: 26 });
(4)删除数据
function deleteUser(id) {
  const transaction = db.transaction(['users'], 'readwrite');
  const store = transaction.objectStore('users');
  const request = store.delete(id);

  request.onsuccess = () => console.log('删除成功');
}

deleteUser(1);
(5)遍历所有数据
function getAllUsers() {
  const transaction = db.transaction(['users'], 'readonly');
  const store = transaction.objectStore('users');
  const request = store.getAll();

  request.onsuccess = (e) => {
    console.log('所有用户:', e.target.result);
  };
}

3. 使用游标遍历数据

function cursorExample() {
  const transaction = db.transaction(['users'], 'readonly');
  const store = transaction.objectStore('users');
  const request = store.openCursor();

  request.onsuccess = (e) => {
    const cursor = e.target.result;
    if (cursor) {
      console.log('当前记录:', cursor.value);
      cursor.continue(); // 移动到下一条记录
    }
  };
}

4. 使用索引查询

function getUsersByName(name) {
  const transaction = db.transaction(['users'], 'readonly');
  const store = transaction.objectStore('users');
  const index = store.index('name');
  const request = index.getAll(name);

  request.onsuccess = (e) => {
    console.log('按姓名查询结果:', e.target.result);
  };
}

注意事项

  1. 异步操作:IndexedDB 的所有操作都是异步的,需通过回调或 Promise 处理。
  2. 事务(Transaction):所有读写操作必须在事务内进行。
  3. 存储上限:通常为 剩余磁盘空间的百分比(Chrome/Firefox)或 250MB(IE)
  4. 复杂查询:支持索引和游标,但不如 SQL 直观。

3. localStorage vs IndexedDB 对比

特性 localStorage IndexedDB
数据类型 仅字符串 支持对象、二进制数据(Blob、ArrayBuffer)
存储上限 5MB 浏览器差异大(通常数百MB到磁盘剩余空间)
操作方式 同步 异步(基于事件或 Promise)
适用场景 简单键值对(如用户设置) 大型结构化数据(如应用状态、离线数据)
查询能力 仅按键查询 支持索引、游标、范围查询

4. 封装 IndexedDB 为 Promise

由于 IndexedDB 是事件驱动的,可以封装为 async/await 风格:

class IDBWrapper {
  constructor(dbName, version) {
    this.dbName = dbName;
    this.version = version;
    this.db = null;
  }

  async init() {
    return new Promise((resolve, reject) => {
      const request = indexedDB.open(this.dbName, this.version);

      request.onerror = (e) => reject(e.target.error);
      request.onsuccess = (e) => {
        this.db = e.target.result;
        resolve(this.db);
      };

      request.onupgradeneeded = (e) => {
        const db = e.target.result;
        if (!db.objectStoreNames.contains('users')) {
          db.createObjectStore('users', { keyPath: 'id' });
        }
      };
    });
  }

  async add(storeName, data) {
    return new Promise((resolve, reject) => {
      const transaction = this.db.transaction(storeName, 'readwrite');
      const store = transaction.objectStore(storeName);
      const request = store.add(data);

      request.onsuccess = () => resolve();
      request.onerror = (e) => reject(e.target.error);
    });
  }

  // 其他方法(get、put、delete等)类似...
}

// 使用示例
(async () => {
  const idb = new IDBWrapper('MyDB', 1);
  await idb.init();
  await idb.add('users', { id: 1, name: 'Bob' });
})();

总结

  • localStorage:简单、同步、适合小数据。
  • IndexedDB:强大、异步、适合大数据和复杂查询。
  • 推荐库
    • localForage(封装 IndexedDB/WebSQL/localStorage,提供类似 localStorage 的 API)。
    • Dexie.js(简化 IndexedDB 操作的轻量级库)。

根据需求选择合适的存储方案!

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。