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('查詢結果集失敗!');
});
}