Logo Vincent
返回文章列表

一篇文章学会IndexedDB

Web
一篇文章学会IndexedDB

【简介】

IndexedDB,web端可以直接使用的数据库,详见: https://developer.mozilla.org/zh-CN/docs/Web/API/IndexedDB_API

【IndexedDB vs LocalStorage】

之前介绍了LocalStorage:一篇文章学会localStorage,

大部分场景下LocalStorage已经可以满足使用了,但还是有一些缺陷,

下面对比一下IndexedDB和LocalStorage的不同

容量大小

|—LocalStorage:最大5M

|—IndexedDB:250M+

数据库特性

|—LocalStorage:只是保存数据,不具备其他特性

|—IndexedDB:具备数据库特性,数据库,表,主键,索引,排序等

同步异步

|—LocalStorage:同步操作

|—IndexedDB:异步操作

简单总结

|—LocalStorage只是本地存储,类似一个小文件存取内容,

|—IndexedDB是web端的数据库,存取数据,搜索数据,数据排序,事务等都支持,而且容量很大

【IndexedDB:数据库和表】

同样的,由于IndexedDB的功能很强大,

使用也稍微复杂,需要一些数据库的基础知识,

创建数据库

要操作IndexedDB,首先需要有一个数据库,创建数据库代码如下

window.indexedDB.open(databaseName);

如果数据库的表结构等发生了变化,需要传入一个新的version再次创建一下

window.indexedDB.open(databaseName, version);

最终返回的db对象在onsuccess回调,或者onupgradeneeded回调内,最终代码如下

/**
 * open db
 * @param {*} databaseName
 * @param {*} version
 * @returns
 */
export const openDB = (databaseName, version) => {
  return new Promise((resolve, reject) => {
    const request = version ? window.indexedDB.open(databaseName, version) : window.indexedDB.open(databaseName);
    request.onerror = (event) => {
      reject(event.target.error);
    };
    request.onsuccess = () => {
      resolve(request.result);
    };
    request.onupgradeneeded = (event) => {
      resolve(event.target.result);
    };
  });
};

创建成功后可以在chrome devtools中的application-storage-IndexedDB内看到创建好的db

查询数据库

创建好后,可以查询一下目前有哪些数据库,代码如下

indexedDB.databases();

会返回目前本地的数据库列表:

删除数据库

当数据库不需要时,可以删除数据库,代码如下

indexedDB.deleteDatabase(databaseName);

创建表

当创建好数据库db后,就可以创建表了

db.createObjectStore(table.name, key);

这里需要传入表名和key

创建索引

创建好表后就可以创建索引了,如下

os.createIndex(name, index, { unique: unique });

创建好表和索引后,在db下就会显示

删除表

删除表,比较简单, 代码如下

db.deleteObjectStore(tableName);

【IndexedDB:操作数据】

创建好数据库和表后,就可以开始操作数据了,

添加数据

需要先创建一个事务,然后添加数据,如下

const tx = db.transaction([tableName], 'readwrite');
const request = tx.objectStore(tableName).add(data);

更新数据

同上,创建事务,然后更新数据,如下

const tx = db.transaction([tableName], 'readwrite');
const request = tx.objectStore(tableName).put(data);

获取数据

同上,创建事务,获取数据

const tx = db.transaction([tableName], 'readonly');
const request = tx.objectStore(tableName).get(key);

数据库内保存的数据如下

删除数据

同样的也可以删除数据

const tx = db.transaction([tableName], 'readwrite');
const request = tx.objectStore(tableName).delete(key);

清空数据

const tx = db.transaction([tableName], 'readwrite');
const request = tx.objectStore(tableName).clear();

获取所有数据

也可以通过某一个index获取所有数据,如下

const tx = db.transaction([tableName], 'readonly');
const os = tx.objectStore(tableName);
const index = os.index(indexName);
const request = index.getAll();

【qiao.db.js】

封装了一个npm包,欢迎使用,https://code.insistime.com/#/qiao.db.js

|—封装数据库和表相关操作

|—封装数据相关操作

【实战一个todolist】

之前使用LocalStorage开发了一个todolist,

文章:一篇文章开发todolist

效果: https://insistime.com/dishi-ls

代码: https://github.com/uikoo9/dishi-monorepo/tree/localstorage

功能比较简单,添加todo,已经点击完成todo,如下

由于LocalStorage不具备数据库特性,

所以像一些排序等操作比较麻烦,

这里使用刚介绍的IndexedDB改造一下

表结构

首先是要设计一个简单的表结构

db_dishi
    |-- t_todos
        |--create_time
        |--todo_content
        |--todo_time
    |--t_dones
        |--done_time
        |--todo_content
        |--todo_time

其中

数据库:db_dishi

表t_todos:待办列表,create_time作为主键,todo_content内容,todo_time待办时间

表t_dones:完成列表,done_time作为主键,todo_content内容,todo_time待办时间

创建数据库

1.使用listDB方法获取数据列表,判断是否已经创建过数据库

2.使用openDB方法创建数据库

const dbName = 'db_dishi';

// check
const dbs = await listDB();
if (dbs && dbs.length && dbs[0].name == dbName) return;

// db
const db = await openDB(dbName);

创建表

1.使用createTable方法创建表

2.表t_todos

// table
const tableTodos = 't_todos';
const tableDones = 't_dones';
const tables = [
  {
    name: tableTodos,
    key: 'create_time',
    index: [
      {
        name: 'todo_time',
        index: ['todo_time', 'todo_content'],
        unique: false,
      },
    ],
  },
  {
    name: tableDones,
    key: 'done_time',
    index: [
      {
        name: 'done_time',
        index: ['done_time'],
        unique: false,
      },
    ],
  },
];
await createTable(db, tables);

表t_todos:主键为create_time,索引todo_time,按todo_time和todo_content字段做索引

表t_dones:主键为done_time,索引done_time,按done_time字段做索引

创建好数据库和表后,如下

添加数据

1.使用save方法添加数据

// save
const create_time = Date.now();
const data = {
  todo_content: todo_content,
  todo_time: todo_time || '_',
  create_time: create_time,
};
const db = await openDB(dbName);
const saveRes = await save(db, tableName, create_time, data);
console.log('add todo:', saveRes);

添加一些数据后的效果如下,可以看到默认是按主键create_time进行排序的

点击todo_time这个索引,可以看到已经按todo_time和todo_content排序了

获取数据

1.使用getAll方法获取索引todo_time的所有数据

2.这样会默认按索引todo_time的规则返回数据,如上

const res = await getAll(db, tableName, 'todo_time');
console.log(res);

删除数据

1.使用get方法获取todo

2.使用del方法删除todo

// todo
const db = await openDB(dbName);
const todo = await get(db, tableTodos, key);

// done
const done = {
  todo_content: todo.todo_content,
  todo_time: todo.todo_time,
  done_time: Date.now(),
};
const saveRes = await save(db, tableDones, null, done);

// del
await del(db, tableTodos, key);
console.log('del todo:', saveRes);

最终效果

1.添加todo

2.添加todo@20221010,记录待办时间

3.点击todo,完成待办

以上代码见: https://github.com/uikoo9/dishi-monorepo/tree/indexeddb

最终效果见: https://insistime.com/dishi-indexeddb

【总结】

1.IndexedDB介绍

2.IndexedDB和LocalStorage对比

3.IndexedDB数据库和表相关操作

4.IndexedDB数据相关操作

5.IndexedDB封装工具: https://code.insistime.com/#/qiao.db.js

6.IndexedDB实战一个todolist,https://insistime.com/dishi-indexeddb

© 2026 vincentqiao.com . 保留所有权利。