IndexedDB 基础操作入门
IndexedDB 打开数据库、建立连接、建表、加索引字段、添加、更新、删除、查询等操作介绍。
示例代码:
/**
* 1. 键值对存储
* 内部采用对象仓库(object store)存放数据,支持所有类型数据的存入。
* 在数据仓库中,数据以"键值对"的形式保存,数据记录都有唯一的主键(不可重复);
*
* 2. 异步
*
* 3. 支持事务
* 在一系列操作步骤中,只要有一步失败,整个事务就会取消,数据库回滚到事务发生之前。
*
* 4. 同源限制
* 每一个数据库对应创建它的域名(只能访问自身域名下的数据库)
*
* 5. 存储空间大
* 一般不少于250MB
*
* 6. 支持二进制存储
* 支持二进制数据(ArrayBuffer, Blob等)
*
* 数据库: IDBDatabase 对象
* 对象仓库: IDBObjectStore 对象
* 索引: IDBIndex 对象
* 事务: IDBTransaction 对象
* 操作请求: IDBRequest 对象
* 指针: IDBCursor 对象
* 主键集合: IDBKeyRange 对象
*
* indexedDB数据库具有版本的概念(同一时刻,只有一个版本的数据库存在)
* 每个数据库包含若干个对象仓库(object store,类似于关系型数据库中的表格)
*/
// 数据库名称
const databaseName = 'todo-list';
// 默认数据库版本
const defaultDatabaseVersion = 1;
/**
* DB instance
* @type {IDBDatabase}
*/
let db;
// 测试数据
const data = [
{ todo: 'minutes', name: 'a', id: 10 },
{ todo: 'day', name: 'b', id: 3 },
{ todo: 'month', name: 'c', id: 9 },
{ todo: 'year', name: 'd', id: 2019 },
{ todo: 'notified', name: 'e', id: 0 },
];
// 表名
const tableName = 'todos';
/**
* 打开数据库请求
* open(name: string, version?: number | undefined): IDBOpenDBRequest;
* IDBOpenDBRequest对象所具备的事件:
* 1. onerror
* 2. onsuccess
* 3. onupgradeneeded(数据库升级事件)
* 4. onblocked
*/
const DBOpenRequest = window.indexedDB.open(databaseName, defaultDatabaseVersion);
// 数据库连接请求失败事件
DBOpenRequest.addEventListener('error', ev => {
console.log('DBOpenRequest Error: ', ev);
});
// 数据库连接请求成功事件
DBOpenRequest.addEventListener('success', () => {
console.info('连接成功!');
db = DBOpenRequest.result;
});
// 在当一个数据库的版本比已经存在的版本还高的时候触发
DBOpenRequest.addEventListener('upgradeneeded', ev => {
db = ev.target.result;
console.log(`版本更新至 ${db.version}`);
db.addEventListener('error', ev => {
console.log('数据库加载时出错', ev);
});
// 主键
const keyPath = 'id';
// 新建表
let store = null;
// 如果目标表不存在
if (!db.objectStoreNames.contains(tableName)) {
store = db.createObjectStore(tableName, {
// 表的主键
keyPath,
});
}
// 新建索引字段
store.createIndex('name', 'name', { unique: false });
console.info('当前表:', store);
});
/**
* *初始化现有的数据项*
*/
function initItems(list) {
for (const item of list) {
addItem(item);
}
}
initItems(data);
/**
* 添加数据项
*/
function addItem(item) {
const store = db.transaction(tableName, 'readwrite').objectStore(tableName);
const request = store.add(item);
request.addEventListener('success', () => {
console.log('数据写入成功!');
});
request.addEventListener('error', () => {
console.log('数据写入失败!');
});
}
// addItem({ id: 1, name: 'k', todo: 'link' });
/**
* 更新单个数据项
*/
function updateItem(item) {
const store = db.transaction(tableName, 'readwrite').objectStore(tableName);
const request = store.put(item);
request.addEventListener('success', () => {
console.log('数据更新成功!');
});
request.addEventListener('error', () => {
console.log('数据更新失败!');
});
}
// updateItem({ id: 1, name: 'j', todo: 'link' });
/**
* 读取指定范围内的数据项列表
* @param {[(string|number), (string|number)]} range
* @param {string} idxName
*/
function readByRange(range, idxName) {
const transaction = db.transaction(tableName, 'readonly');
const store = transaction.objectStore(tableName).index(idxName);
const [start, end] = range;
// 查询范围
const keyRange = window.IDBKeyRange.bound(start, end);
// 查询游标对象
const cursor = store.openCursor(keyRange);
cursor.addEventListener('success', ev => {
const res = ev.target.result;
if (!res) {
console.log('没有更多数据了!');
return;
}
console.info('条目:', res.value);
res.continue();
});
cursor.addEventListener('error', ev => {
console.log('范围查询失败:', ev);
});
}
/**
* 读取单个数据项(根据当前索引键的特定值)
*/
function readItem(id) {
const transaction = db.transaction([tableName]);
const store = transaction.objectStore(tableName);
const request = store.get(id);
request.addEventListener('success', () => {
if (!request.result) {
console.log('未获得数据记录');
return;
}
console.info('id: ' + request.result.id);
console.info('name: ' + request.result.name);
console.info('todo: ' + request.result.todo);
});
request.addEventListener('error', () => {
console.log('事务执行失败!');
});
}
/**
* 删除匹配到的数据项(id值)
*/
function deleteItem(id) {
const store = db.transaction(tableName, 'readwrite').objectStore(tableName);
const request = store.delete(id);
request.addEventListener('success', () => {
console.log('数据删除成功!');
});
request.addEventListener('error', () => {
console.log('数据删除失败!');
});
}
/**
* 查询所有数据项
*/
function queryAll() {
const store = db.transaction(tableName, 'readonly').objectStore(tableName);
const cursor = store.openCursor();
cursor.addEventListener('success', evt => {
const res = evt.target.result;
if (!res) {
console.log('没有更多数据了!');
return;
}
console.info('id: ' + res.value.id);
console.info('name: ' + res.value.name);
console.info('todo: ' + res.value.todo);
res.continue();
});
cursor.addEventListener('error', () => {
console.log('查询结果集失败!');
});
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?