let _IDBDatabase;//數(shù)據(jù)庫(kù)對(duì)象/** * 初始化或升級(jí)數(shù)據(jù)庫(kù)(動(dòng)態(tài)對(duì)比增刪改上一版本對(duì)象倉(cāng)庫(kù)和索引) * * @param {String} dbName 數(shù)據(jù)庫(kù)名稱 * @param {Number} dbVersion 數(shù)據(jù)庫(kù)版本 * @param {Array} objectStoreArr 對(duì)象倉(cāng)庫(kù)名稱列表,格式如下:[{ name: ‘userStore’, index: [{ keys: ‘name,age’, unique: true }]}] * * @returns Promise對(duì)象,then(IDBDatabase) */export let initDB = (dbName, dbVersion, objectStoreArr) => new Promise((resolve, reject) => { let _IDBRequest = window.indexedDB.open(dbName, dbVersion); _IDBRequest.onsuccess = event => { _IDBDatabase = event.target.result; resolve(_IDBDatabase); }; _IDBRequest.onerror = event => reject(event); _IDBRequest.onupgradeneeded = event => { let oldObjectStoreNames = event.target.result.objectStoreNames; let newObjectStoreNames = objectStoreArr.map(o => o.name); if (oldObjectStoreNames.length === 0 && newObjectStoreNames && newObjectStoreNames.length > 0) //原對(duì)象倉(cāng)庫(kù)為空,新對(duì)象倉(cāng)庫(kù)不為空,直接添加新對(duì)象倉(cāng)庫(kù) for (let newObjectStoreName of newObjectStoreNames) { let newObjectStore = event.target.result.createObjectStore(newObjectStoreName, { keyPath: ‘id’ }); let newIndexArr = objectStoreArr.filter(o => o.name === newObjectStoreName)[0].index ?? []; for (let index of newIndexArr) newObjectStore.createIndex(index.keys, index.keys.split(‘,’), { unique: index.unique ?? false }); } else {//原對(duì)象倉(cāng)庫(kù)不為空,則需要根據(jù)新舊對(duì)象倉(cāng)庫(kù)對(duì)比情況,決定添加刪除或編輯 for (let oldObjectStoreName of oldObjectStoreNames) if (!newObjectStoreNames.some(newObjectStoreName => newObjectStoreName === oldObjectStoreName))//新對(duì)象倉(cāng)庫(kù)中不存在的就對(duì)象倉(cāng)庫(kù),直接刪除 event.target.result.deleteObjectStore(oldObjectStoreName); newObjectStoreNames.forEach(newObjectStoreName => { if (oldObjectStoreNames.contains(newObjectStoreName)) {//新舊對(duì)象倉(cāng)庫(kù)都存在的,編輯 let oldObjectStore = event.target.transaction.objectStore(newObjectStoreName); let newIndexArr = objectStoreArr.filter(o => o.name === newObjectStoreName)[0].index ?? []; let oldIndexNames = oldObjectStore.indexNames; let newIndexNames = newIndexArr.map(o => o.keys); for (let oldIndexName of oldIndexNames)//舊對(duì)象倉(cāng)庫(kù)中存在索引,新對(duì)象倉(cāng)庫(kù)中不存在的索引,刪除 if (!newIndexNames.some(newIndexName => newIndexName === oldIndexName)) oldObjectStore.deleteIndex(oldIndexName); for (let newIndexName of newIndexNames) //新對(duì)象倉(cāng)庫(kù)中存在索引,舊對(duì)象倉(cāng)庫(kù)中不存在索引,添加 if (!oldIndexNames.contains(newIndexName)) oldObjectStore.createIndex(newIndexName, newIndexName.split(‘,’), { unique: newIndexArr.filter(o => o.keys === newIndexName)[0].unique ?? false }); } else {//新對(duì)象倉(cāng)庫(kù)有,舊對(duì)象倉(cāng)庫(kù)沒(méi)有,添加 let newObjectStore = event.target.result.createObjectStore(newObjectStoreName, { keyPath: ‘id’ }); let newObjectStoreIndexs = objectStoreArr.filter(o => o.name === newObjectStoreName)[0].index ?? []; for (let index of newObjectStoreIndexs) newObjectStore.createIndex(index.keys, index.keys.split(‘,’), { unique: index.unique ?? false }); } }) } };});
1.初始化或升級(jí)IDB,調(diào)用如下
//調(diào)用示例initDB(“testDB”, 1, [{ name: ‘userStore’, index: [{ keys: ‘name,age’, unique: true }, { keys: ‘age’, unique: false }] }, { name: ‘scoreStore’ }]).then(res => { });
2.添加數(shù)據(jù)
/** * 添加數(shù)據(jù) * * @param {String} storeName 對(duì)象倉(cāng)庫(kù)名稱 * @param {Object} data 對(duì)象數(shù)據(jù) * * @returns Promise對(duì)象,then(IDBRequest) */export let adData = (storeName, data) => new Promise((resolve, reject) => { let _IDBRequest = _IDBDatabase.transaction(storeName, ‘readwrite’).objectStore(storeName).add(data); _IDBRequest.onsuccess = event => resolve(event.target); _IDBRequest.onerror = event => reject(event);});//調(diào)用示例for (let i = 1; i <= 100; i++) { adData('userStore', { id: i, name: '張三' + i, age: Math.floor((Math.random() * 10) + 10) })}
3.刪除數(shù)據(jù)
/** * 刪除數(shù)據(jù) * * @param {String} storeName 對(duì)象倉(cāng)庫(kù)名稱 * @param {Number} id 對(duì)象數(shù)據(jù)id * * @returns Promise對(duì)象,then(IDBRequest) */export let rmDataById = (storeName, id) => new Promise((resolve, reject) => { let _IDBRequest = _IDBDatabase.transaction(storeName, ‘readwrite’).objectStore(storeName).delete(id); _IDBRequest.onsuccess = event => resolve(event.target); _IDBRequest.onerror = event => reject(event);});//調(diào)用示例rmDataById(‘userStore’, 3).then(res => console.log(res));
4.清空對(duì)象數(shù)據(jù)
/** * 清空對(duì)象數(shù)據(jù) * * @param {String} storeName 對(duì)象倉(cāng)庫(kù)名稱 * * @returns Promise對(duì)象,then(IDBRequest) */export let clearData = (storeName) => new Promise((resolve, reject) => { let _IDBRequest = _IDBDatabase.transaction(storeName, ‘readwrite’).objectStore(storeName).clear(); _IDBRequest.onsuccess = event => resolve(event.target); _IDBRequest.onerror = event => reject(event);});//調(diào)用示例clearData(‘userStore’).then(res => console.log(res));
5.對(duì)象倉(cāng)庫(kù)記錄數(shù)據(jù)
/** * 對(duì)象倉(cāng)庫(kù)記錄數(shù) * * @param {String} storeName 對(duì)象倉(cāng)庫(kù)名稱 * @param {IDBKeyRange} query IDBKeyRange(可選) * @param {String} indexKeys 索引keys(缺省為id,可選) * * @returns Promise對(duì)象,then(數(shù)據(jù)倉(cāng)庫(kù)記錄數(shù)) */export let countData = (storeName, query, indexKeys) => new Promise((resolve, reject) => { let objectStore = _IDBDatabase.transaction(storeName, ‘readwrite’).objectStore(storeName); if (indexKeys) objectStore = objectStore.index(indexKeys); let _IDBRequest = query ? objectStore.count(query) : objectStore.count(); _IDBRequest.onsuccess = event => resolve(event.target.result); _IDBRequest.onerror = event => reject(event);});//調(diào)用示例countData(‘userStore’, IDBKeyRange.bound([10], [12]), ‘age’).then(res => console.log(res));
6.編輯數(shù)據(jù)
/** * 編輯數(shù)據(jù) * * @param {String} storeName 對(duì)象倉(cāng)庫(kù)名稱 * @param {Object} data 對(duì)象數(shù)據(jù) * @returns Promise對(duì)象,then(IDBRequest) */export let mdDataById = (storeName, data) => new Promise((resolve, reject) => { let _IDBRequest = _IDBDatabase.transaction(storeName, ‘readwrite’).objectStore(storeName).put(data); _IDBRequest.onsuccess = event => resolve(event.target); _IDBRequest.onerror = event => reject(event);});//調(diào)用示例mdDataById(‘userStore’, { id: 2, name: ‘李四222’, age: 18 }).then(res => console.log(res))
7.根據(jù)id查詢數(shù)據(jù)
/** * 根據(jù)id查詢數(shù)據(jù) * * @param {String} storeName 對(duì)象倉(cāng)庫(kù)名稱 * @param {Number} id 主鍵key * * @returns Promise對(duì)象,then(數(shù)據(jù)對(duì)象) */export let getDataById = (storeName, id) => new Promise((resolve, reject) => { let _IDBRequest = _IDBDatabase.transaction(storeName, ‘readwrite’).objectStore(storeName).get(id); _IDBRequest.onsuccess = event => resolve(event.target.result); _IDBRequest.onerror = event => reject(event);});//調(diào)用示例getDataById(‘userStore’, 5).then(res => console.log(res))
8.查詢數(shù)據(jù)列表
/** * 查詢數(shù)據(jù)列表(自定義索引的query參數(shù)為數(shù)組格式,IDBKeyRange.bound([10], [20])) * * @param {String} storeName 對(duì)象倉(cāng)庫(kù)名稱 * @param {IDBKeyRange} query IDBKeyRange(可選) * @param {IDBCursorDirection} direction IDBCursorDirection枚舉類型:”next”,”nextunique”,”prev”,”prevunique”(可選) * @param {String} indexKeys 索引keys(缺省為id,可選) * * @returns Promise對(duì)象,then(數(shù)據(jù)對(duì)象數(shù)組) */export let queryData = (storeName, query, direction, indexKeys) => new Promise((resolve, reject) => { let objectStore = _IDBDatabase.transaction(storeName).objectStore(storeName); if (indexKeys) objectStore = objectStore.index(indexKeys); let _IDBRequest = query ? (direction ? objectStore.openCursor(query, direction) : objectStore.openCursor(query)) : objectStore.openCursor(); let arr = []; _IDBRequest.onsuccess = event => { let cursor = event.target.result if (cursor) { arr.push(cursor.value); cursor.continue(); } else resolve(arr); }; _IDBRequest.onerror = event => reject(event);});//調(diào)用示例queryData(‘userStore’, IDBKeyRange.bound(1, 11, false, true)).then(res => console.log(res));
9.分頁(yè)查詢
/** * 分頁(yè)查詢 * * @param {String} storeName 對(duì)象倉(cāng)庫(kù)名稱 * @param {Number} pageNo 頁(yè)碼 * @param {Number} pageSize 頁(yè)面大小 * @param {IDBKeyRange} query IDBKeyRange(可選) * @param {IDBCursorDirection} direction IDBCursorDirection枚舉類型:”next”,”nextunique”,”prev”,”prevunique”(可選) * @param {String} indexKeys 索引keys(缺省為id,可選) * @returns Promise對(duì)象,then(分頁(yè)數(shù)據(jù) total、pages、data) */export let queryPage = (storeName, pageNo, pageSize, query, direction, indexKeys) => countData(storeName, query, indexKeys).then(total => new Promise((resolve, reject) => { let pages = 0, data = [], objectStore = _IDBDatabase.transaction(storeName).objectStore(storeName); if (indexKeys) objectStore = objectStore.index(indexKeys); let _IDBRequest = query ? (direction ? objectStore.openCursor(query, direction) : objectStore.openCursor(query)) : objectStore.openCursor(); let isAdvance = true; _IDBRequest.onsuccess = event => { let cursor = event.target.result if (cursor) { if (isAdvance && data.length === 0 && pageNo > 1) { isAdvance = false; cursor.advance((pageNo – 1) * pageSize); } else { data.push(cursor.value); if (data.length === pageSize) { resolve({ total: total, pages: Math.ceil(total / pageSize), data: data }) return; } cursor.continue(); } } else resolve({ total: total, pages: pages, data: data }) }; _IDBRequest.onerror = event => reject(event);}));//調(diào)用示例queryPage(‘userStore’, 1, 9).then(res => console.log(res))
10.關(guān)閉數(shù)據(jù)庫(kù)
/** * 關(guān)閉數(shù)據(jù)庫(kù) * * @returns void */export let closeDB = () => _IDBDatabase.close();//調(diào)用示例closeDB()