前端数据库indexedDB入门
什么是indexDB
????????學(xué)習(xí)文檔:
- 阮一峰老師的分享文檔:瀏覽器數(shù)據(jù)庫 IndexedDB 入門教程 - 阮一峰的網(wǎng)絡(luò)日志
- 官方API文檔,純英文,不過提供的代碼很有用:Indexed Database API 3.0
????????indexDB是HTML5的新概念,indexedDB是一個用于在瀏覽器中存儲較大數(shù)據(jù)結(jié)構(gòu)的Web API,并且提供了索引功能以實(shí)現(xiàn)高性能查找。不同于其他基于SQL的關(guān)系型數(shù)據(jù)庫,indexedDB是一個事務(wù)型的數(shù)據(jù)庫系統(tǒng),會將數(shù)據(jù)集作為個體對象存儲,數(shù)據(jù)形式使用的是JSON,而不是列數(shù)固定的表格來存儲數(shù)據(jù)的。
????????indexDB比本地存儲很強(qiáng)大,而且存儲大小是250m以上(受計(jì)算機(jī)硬件和瀏覽器廠商的限制)。
- indexDB優(yōu)點(diǎn)是:存儲容量大;支持異步操作;具有事務(wù)特點(diǎn);
- indexDB缺點(diǎn)是:不支持DO操作;不能跨域。
????????indexDB中的對象:
- 數(shù)據(jù)庫:IDBDatabase 對象
- 對象倉庫:IDBObjectStore 對象
- 索引: IDBIndex 對象
- 事務(wù): IDBTransaction 對象
- 操作請求:IDBRequest 對象
- 指針(游標(biāo)): IDBCursor 對象
- 主鍵集合:IDBKeyRange 對象
????????基本語法:
| 語法 | 作用 |
| window.indexedDB.open(數(shù)據(jù)庫名,版本號) | 打開數(shù)據(jù)庫(如果數(shù)據(jù)庫不存在則創(chuàng)建一個新的庫) |
| .onerror | 數(shù)據(jù)庫操作過程中出錯時觸發(fā) |
| .onupgradeneeded | 創(chuàng)建一個新的數(shù)據(jù)庫或者修改數(shù)據(jù)庫版本號時觸發(fā) |
| .onsuccess | 數(shù)據(jù)庫成功完成所有操作時觸發(fā) |
| .createObjectStore(對象倉庫名稱,keypath) | 創(chuàng)建對象倉庫 |
| .createIndex(索引名稱,keypath,objectParameters) | 建立索引 |
| .transaction(對象倉庫名稱) || .transaction(對象倉庫名稱,‘readwrite’) | 創(chuàng)建一個事務(wù) || 創(chuàng)建一個事務(wù),并要求具有讀寫權(quán)限 |
| .objectStore(對象倉庫名稱) | 獲取對象倉庫 |
| .get ( num ) || .getAll() | 獲取數(shù)據(jù) || 獲取全部數(shù)據(jù) |
| .add( data ) | 添加數(shù)據(jù) |
| .put( newdata ) | 修改數(shù)據(jù) |
| .delete ( keypath ) | 刪除數(shù)據(jù) |
????????Demo:
????????關(guān)于具體應(yīng)用的demo可以看我的gitee上的Demo:
https://gitee.com/yinlingyun123/dragVuehttps://gitee.com/yinlingyun123/dragVue
indexDB基礎(chǔ)操作:
????????indeDB和一般的數(shù)據(jù)庫一樣,創(chuàng)建/打開數(shù)據(jù)庫,創(chuàng)建/打開表,對數(shù)據(jù)的增刪查改等都是其基本功能。
????????1、判斷瀏覽器是否支持IndexDB
function justifyIndexDEB(){if("indexedDB" in window) {// 支持console.log(" 支持indexedDB...");} else {// 不支持console.log("不支持indexedDB...");} }????????2、不同瀏覽器兼容
//數(shù)據(jù)庫對象 window.indexedDB =window.indexedDB||window.webikitIndexedDB||window.mozIndexedDB||window.msIndexedDB; //數(shù)據(jù)庫事務(wù) window.IDBTransaction = window.IDBTransaction||window.webikitIDBTransaction||window.mozIDBTransaction||window.msIDBTransaction; //數(shù)據(jù)庫查詢條件window.IDBKeyRange = window.IDBKeyRange||window.webkitIDBKeyRange||window.mozIDBKeyRange||window.msIDBKeyRange; //游標(biāo) window.IBDCursor = window.IBDCursor ||window.webkitIBDCursor ||window.mozIBDCursor ||window.msIBDCursor ;????????3、創(chuàng)建/打開數(shù)據(jù)庫
????????如果存在就打開,不存在就創(chuàng)建一個indexDB數(shù)據(jù)庫:
const req = window.indexedDB.open(databaseName, version) // 數(shù)據(jù)庫名稱,版本號 let that = this; req.onsuccess = function (event) { // 監(jiān)聽數(shù)據(jù)庫創(chuàng)建成功事件that.indexDB = event.target.result // 數(shù)據(jù)庫對象console.log('數(shù)據(jù)庫打開成功') } req.onerror = function (error) {console.log('數(shù)據(jù)庫打開報(bào)錯') } req.onupgradeneeded = function (event) {// 數(shù)據(jù)庫創(chuàng)建或升級的時候會觸發(fā)console.log('數(shù)據(jù)庫創(chuàng)建或升級') }????????4、創(chuàng)建/打開/刪除數(shù)據(jù)表
????????在indexedDB中,是使用objectStore來存儲數(shù)據(jù)呢。objectStore相當(dāng)于一張表,但是objectStore并不想mysql中的表一樣,具有一列一列的結(jié)構(gòu),它只有兩列,一列是keypath(鍵值),另一列就是存儲的數(shù)據(jù)了,存儲的數(shù)據(jù)一般用JavaScript中的對象來表示。每一條數(shù)據(jù)都和一個鍵相關(guān)聯(lián)。
????????存儲時可以使用每條記錄中的某個指定字段作為鍵值(keyPath),也可以使用自動生成的遞增數(shù)字作為鍵值(keyGenerator),也可以不指定。選擇鍵的類型不同,objectStore可以存儲的數(shù)據(jù)結(jié)構(gòu)也有差異。
| 鍵類型 | 存儲數(shù)據(jù) |
| 不使用 | 任意值,但是沒添加一條數(shù)據(jù)的時候需要指定鍵參數(shù) |
| keyPath | Javascript對象,對象必須有一屬性作為鍵值 |
| keyGenerator | 任意值 |
| 都使用 | Javascript對象,如果對象中有keyPath指定的屬性則不生成新的鍵值,如果沒有自動生成遞增鍵值,填充keyPath指定屬性 |
????????創(chuàng)建表:
????????通過數(shù)據(jù)庫實(shí)例的createObjectStore(storeName,keyType)進(jìn)行創(chuàng)建objectStore。這個方法有兩個參數(shù),一個是objectStore的名字,一個是創(chuàng)建表的鍵類型。
????????創(chuàng)建表相當(dāng)于修改了數(shù)據(jù)庫的模式,所以這個操作應(yīng)該放到onupgradeneeded中:
req.onupgradeneeded = function (event) {// 數(shù)據(jù)庫創(chuàng)建或升級的時候會觸發(fā)let db = event.target.resultlet storeName = 'product' // 表名if(!db.objectStoreNames.contains(storeName)) {// keyPath是主鍵鍵值,也可以不傳然后設(shè)定autoIncrement:true自動創(chuàng)建鍵值db.createObjectStore(storeName,{keyPath:'key'});}//db.deleteObjectStore(storeName);刪除數(shù)據(jù)倉庫方法,參數(shù)為數(shù)據(jù)倉庫名稱 }????????5、創(chuàng)建/刪除索引
????????索引可以用來搜索,主鍵是默認(rèn)的索引。
????????只能針對被設(shè)為索引的屬性值進(jìn)行檢索,不能針對沒有被設(shè)為索引的屬性值進(jìn)行檢索。
????????索引包含有聯(lián)合索引,唯一索引,對數(shù)組字段建索引等等擴(kuò)展功能,有需要的可以自己探索!
req.onupgradeneeded = function (event) {// 數(shù)據(jù)庫創(chuàng)建或升級的時候會觸發(fā)db = event.target.resultlet storeName = 'product' // 表名if (!db.objectStoreNames.contains(storeName)) { // 判斷表是否存在let objectStore = db.createObjectStore(storeName, { keyPath: 'key',autoIncrement: true })// 創(chuàng)建索引// indexName索引列名稱// indexKey索引鍵值objectStore.createIndex('indexName', 'indexKey', { unique: false }) // 創(chuàng)建索引 可以讓你搜索任意字段//objectStore.deleteIndex("indexName");刪除索引} }????????給對象倉庫(數(shù)據(jù)庫表)創(chuàng)建索引,需要使用對象倉庫的createIndex()函數(shù),param1 索引名稱,param2 配置索引的鍵值,param3 配置對象 配置該屬性是否是唯一的。
????????param3 配置對象可配置屬性:
- unique 唯一
- multiEntry 對于有多個值的主鍵數(shù)組,每個值將在索引里面新建一個條目,否則主鍵數(shù)組對應(yīng)一個條目
????????6、添加數(shù)據(jù)
// this.indexDB創(chuàng)建數(shù)據(jù)庫時候存下的數(shù)據(jù)庫對象 // itemName是存儲的key // newValue是存儲的value const transaction = this.indexDB.transaction('product', "readwrite"); const store = transaction.objectStore('product'); const request = store.put({ key: 'item', value: '<p>3333</p>' }); // const request = store.add({ key: 'item', value: '<p>3333</p>' }); //add方法也可以 request.onsuccess=function(e) {console.info('添加數(shù)據(jù)成功') }; request.onerror=function(e) {console.info('添加數(shù)據(jù)失敗') };????????7、獲取數(shù)據(jù)
????????get方法是獲取定義的主鍵鍵值為輸入數(shù)據(jù)的第一條數(shù)據(jù),如果想獲取匹配的所有數(shù)據(jù)就得用getAll方法進(jìn)行獲取。不過get、getAll方法需要查詢整張表來獲得結(jié)果,數(shù)據(jù)量大的時候效率很低。所以在日常使用中都是通過添加索引然后使用游標(biāo)查詢索引獲取想要的數(shù)據(jù)。
// this.indexDB創(chuàng)建數(shù)據(jù)庫時候存下的數(shù)據(jù)庫對象 // itemName是存儲的key // newValue是存儲的value const transaction = this.indexDB.transaction('product', 'readwrite'); const store = transaction.objectStore('product'); const request=store.get('item'); request.onsuccess=function(e) {store.put({ key: 'item', value: '<p>3333</p>' });console.info('獲取數(shù)據(jù)成功') }; request.onerror=function(e) {console.info('獲取數(shù)據(jù)失敗') };????????8、更新數(shù)據(jù)
????????更新數(shù)據(jù)操作其實(shí)就是添加和獲取合二為一,在獲取成功的回調(diào)函數(shù)里面進(jìn)行數(shù)據(jù)的添加從而覆蓋掉原來的數(shù)據(jù):
// this.indexDB創(chuàng)建數(shù)據(jù)庫時候存下的數(shù)據(jù)庫對象 // itemName是存儲的key // newValue是存儲的value const transaction = this.indexDB.transaction('product', 'readwrite'); const store = transaction.objectStore('product'); const request=store.get('item'); request.onsuccess=function(e) {store.put({ key: 'item', value: '<p>4444</p>' }); };?????????9、刪除數(shù)據(jù)
// this.indexDB創(chuàng)建數(shù)據(jù)庫時候存下的數(shù)據(jù)庫對象 // itemName是存儲的key // newValue是存儲的value const transaction = this.indexDB.transaction('product', 'readwrite'); const store = transaction.objectStore('product'); const request=store.delete('item'); request.onsuccess=function(e) {console.info('刪除數(shù)據(jù)成功') }; request.onerror=function(e) {console.info('刪除數(shù)據(jù)失敗') };????????10、遍歷數(shù)據(jù)
????????使用指針對象IDBCursor遍歷數(shù)據(jù)
objectStore.openCursor().onsuccess = function () {const cursor = e.target.resultif (cursor) {console.log(cursor.key) // 當(dāng)前遍歷數(shù)據(jù)的主鍵console.log(cursor.value) // 當(dāng)前遍歷的數(shù)據(jù)cursor.continue() // 繼續(xù)下一個} }????????可以通過配置IDBKeyRange來設(shè)定查詢范圍
// 游標(biāo)查詢范圍內(nèi)的多個: // 除了bound 還有 only,lowerBound, upperBound 方法,還可以指明是否排除邊界值 const range = IDBKeyRange.bound([min1, min2, min3], [max1, max2, max3]) // 傳入的 prev 表示是降序遍歷游標(biāo),默認(rèn)是next表示升序;如果索引不是unique的,而你又不想訪問重復(fù)的索引,可以使用nextunique或prevunique,這時每次會得到key最小的那個數(shù)據(jù) dbIndex.openCursor(range, "prev").onsuccess = e => { let cursor = e.target.result;if (cursor) {let data = cursor.value // 數(shù)據(jù)的處理就在這里。。。 [ 理解 cursor.key,cursor.primaryKey,cursor.value ]cursor.continue()} else {// 游標(biāo)遍歷結(jié)束! } }????????需要說明的是?IDBKeyRange.bound([min1, min2, min3], [max1, max2, max3])? ?的范圍如下:
max1 > min1 || max1 === min1 && max2 > min2 || max1 === min1 && max2 === min2 && max3 > min3 // 好好理解一下這個 bound 的含義吧 !?????????11、使用promise封裝上述方法
? ? ? ? a.使用promise封裝 open方法
/*** 打開/創(chuàng)建數(shù)據(jù)庫* @param {object} dbName 數(shù)據(jù)庫的名字* @param {string} storeName 倉庫名稱* @param {string} version 數(shù)據(jù)庫的版本* @param {string} keyPath 主鍵鍵值,不傳就自動創(chuàng)建主鍵* @param {Array} index 索引數(shù)組* @return {object} 該函數(shù)會返回一個數(shù)據(jù)庫實(shí)例*/ type StoreOptions = {autoIncrement: boolean;keyPath?: string; }; export const openDB = function (dbName: string,version: number,storeName: string,keyPath?: string,index?: Array<any[]> | undefined ) {return new Promise((resolve, reject) => {// 兼容瀏覽器// eslint-disable-next-line @typescript-eslint/ban-ts-comment// @ts-ignoreconst { webkitIndexedDB, indexedDB, mozIndexedDB, msIndexedDB } = window;const indexDB = indexedDB || mozIndexedDB || webkitIndexedDB || msIndexedDB;let db = null;const request = indexDB.open(dbName, version);// 操作成功request.onsuccess = function (event: any) {db = event?.target?.result; // 數(shù)據(jù)庫對象resolve({ code: 0, success: true, data: db, msg: "數(shù)據(jù)庫打開成功!" });};// 操作失敗request.onerror = function () {resolve({ code: -1, success: false, data: null, msg: "數(shù)據(jù)庫打開失敗!" });};// 創(chuàng)建表和索引request.onupgradeneeded = function (event: any) {// 數(shù)據(jù)庫創(chuàng)建或升級的時候會觸發(fā)db = event?.target?.result; // 數(shù)據(jù)庫對象const storeOptions: StoreOptions = {autoIncrement: true,};if (keyPath && keyPath !== "") {storeOptions.autoIncrement = false;storeOptions.keyPath = keyPath;}// 創(chuàng)建表if (!db.objectStoreNames.contains(storeName)) {const store = db.createObjectStore(storeName, storeOptions);// 創(chuàng)建索引// indexName索引列名稱// indexKey索引鍵值if (index && index.length > 0) {index.forEach((item: any) => {if (!item.indexName ||!item.indexKey ||item.options.unique === undefined) {reject("索引格式錯誤,請參照格式{indexName:'indexName',indexKey:'indexKey',{unique: false}}");}store.createIndex(item.indexName, item.indexKey, item.options);});}}};}); };????????b.使用promise封裝 add方法?
/*** 新增數(shù)據(jù)* @param {object} db 數(shù)據(jù)庫實(shí)例* @param {string} storeName 倉庫名稱* @param {object} dataConfig 添加的數(shù)據(jù)集合**/ export const addData = function (db: any, storeName: string, dataConfig: any) {return new Promise((resolve, reject) => {if (!db) {reject("數(shù)據(jù)庫不存在或沒有初始化");}if (!dataConfig || !dataConfig.value) {reject("value是必傳項(xiàng),參照格式{[keyPath]:'key',value:'value'}");}const req = db.transaction([storeName], "readwrite").objectStore(storeName) // 倉庫對象.add(dataConfig);// 操作成功req.onsuccess = function () {resolve({ code: 0, success: true, data: null, msg: "數(shù)據(jù)寫入成功!" });};// 操作失敗req.onerror = function () {const data = {code: -1,success: false,data: null,msg: "數(shù)據(jù)寫入失敗!",};resolve(data);};}); };????????c.使用promise封裝 put方法?
/*** 更新數(shù)據(jù)* @param {object} db 數(shù)據(jù)庫實(shí)例* @param {string} storeName 倉庫名稱* @param {object} dataConfig 更新的數(shù)據(jù)集合*/ export const updateData = function (db: any,storeName: string,dataConfig: any ) {return new Promise((resolve, reject) => {if (!db) {reject("數(shù)據(jù)庫不存在或沒有初始化");}if (!dataConfig || !dataConfig.value) {reject("value是必傳項(xiàng),參照格式{[keyPath]:'key',value:'value'}");}const req = db.transaction([storeName], "readwrite").objectStore(storeName).put(dataConfig);// 操作成功req.onsuccess = function () {resolve({ code: 0, success: true, data: null, msg: "數(shù)據(jù)更新成功!" });};// 操作失敗req.onerror = function () {const data = {code: -1,success: false,data: null,msg: "數(shù)據(jù)更新失敗!",};resolve(data);};}); };????????d.使用promise封裝 get方法
/*** 查詢數(shù)據(jù)* @param {object} db 數(shù)據(jù)庫實(shí)例* @param {string} storeName 倉庫名稱* @param {string} key 數(shù)據(jù)主鍵**/ export const getData = function (db: any, storeName: string, key: string) {return new Promise((resolve, reject) => {if (!db) {reject("數(shù)據(jù)庫不存在或沒有初始化");}const req = db.transaction([storeName], "readonly").objectStore(storeName) // 倉庫對象.get(key);// 操作成功req.onsuccess = function (e: { target: { result: any } }) {resolve({code: 0,success: true,data: e?.target?.result,msg: "數(shù)據(jù)獲取成功!",});};// 操作失敗req.onerror = function () {const data = {code: -1,success: false,data: null,msg: "數(shù)據(jù)獲取失敗!",};resolve(data);};}); };????????d.使用promise封delete方法?
/*** 刪除數(shù)據(jù)* @param {object} db 數(shù)據(jù)庫實(shí)例* @param {string} storeName 倉庫名稱* @param {string} key 數(shù)據(jù)主鍵**/ export const deleteData = function (db: any, storeName: string, key: string) {return new Promise((resolve, reject) => {if (!db) {reject("數(shù)據(jù)庫不存在或沒有初始化");}const req = db.transaction([storeName], "readwrite").objectStore(storeName) // 倉庫對象.delete(key);// 操作成功req.onsuccess = function (e: { target: { result: any } }) {resolve({code: 0,success: true,data: e?.target?.result,msg: "數(shù)據(jù)刪除成功!",});};// 操作失敗req.onerror = function () {const data = {code: -1,success: false,data: null,msg: "數(shù)據(jù)刪除失敗!",};resolve(data);};}); };????????e.使用promise封裝 游標(biāo)查詢方法?
/*** 使用游標(biāo)查詢數(shù)據(jù)* @param {object} db 數(shù)據(jù)庫實(shí)例* @param {string} storeName 倉庫名稱* @param {string} indexKey 查詢的索引的鍵值* @param {string} index 查詢的索引值**/ export const getIndexData = function (db: any,storeName: string,indexKey: string,index: string ) {return new Promise((resolve, reject) => {if (!db) {reject("數(shù)據(jù)庫不存在或沒有初始化");}const keyRange = IDBKeyRange.only(index);const req = db.transaction([storeName], "readonly").objectStore(storeName) // 倉庫對象.index(indexKey).openCursor(keyRange, "next");// 操作成功req.onsuccess = function (e: { target: { result: any } }) {resolve({code: 0,success: true,data: e?.target?.result,msg: "數(shù)據(jù)查詢成功!",});};// 操作失敗req.onerror = function () {const data = {code: -1,success: false,data: null,msg: "數(shù)據(jù)查詢失敗!",};resolve(data);};}); };????????詳細(xì)封裝文件查看請戳鏈接:
https://gitee.com/yinlingyun123/dragVue/blob/master/src/utils/indexDB.tsxhttps://gitee.com/yinlingyun123/dragVue/blob/master/src/utils/indexDB.tsx
indexDB常見錯誤:
????????1.transaction出錯
Uncaught DOMException: Failed to execute ‘transaction’ on ‘IDBDatabase’: A version change transaction is running.
????????錯誤原因:
????????有一個事務(wù)在運(yùn)行,不能打開第二個事務(wù).
????????解決辦法:
????????將transaction相關(guān)的代碼寫在objectStore.transaction.oncomplete中
var request = indexedDB.open('sql', 2); request.onupgradeneeded = function(event) {var db = event.target.result;var objectStore = db.createObjectStore("customers", { keyPath: "ssn" });objectStore.transaction.oncomplete = function(event) {var customerObjectStore = db.transaction("customers", "readwrite").objectStore("customers").add({ id: "555-55-5555", name: "Donna", age: 32, email: "donna@home.org" });}; };????????2.Cannot read錯誤
Uncaught TypeError: Cannot read property ‘xxx’ of undefined
? ? ? ? 錯誤原因:
????????因?yàn)閕ndexDB代碼都是異步代碼,所以有些還沒有定義部分的代碼可能會優(yōu)先執(zhí)行,導(dǎo)致這個變量為undefined
? ? ? ? 3.嘗試讀取數(shù)據(jù)時候報(bào)錯
Uncaught InvalidStateError: Failed to read the ‘result’ property from ‘IDBRequest’: The request has not finished
????????錯誤示范:
var r = indexedDB.open(); var db = null; r.onsuccess = function(event) { db = event.target.result); }????????正確示范:
var r = indexedDB.open(); r.onsuccess = function(event) {var db = event.target.result; };????????4.Put的時候報(bào)錯
failed to execute ‘put’ on ‘idbobjectstore’ evaluating the object store’s key path did not yield a value
? ? ? ? 錯誤原因:????????
????????儲存數(shù)據(jù)的時候必須要帶上object store的key一起儲存,或者使用一個key:generator({autoIncrement: true})
? ? ? ? 示例:
var store = db.createObjectStore('my_store', {keyPath: 'key'}); store.put({key: 11, value: 33}); // OK store.put({value: 66}); // throws, since 'key' is not present var store = db.createObjectStore('my_store', {keyPath: 'key', autoIncrement: true}); store.put({key: 11, value: 33}); // OK, key generator set to 11 store.put({value: 66}); // OK, will have auto-generated key 12????????5.createObjectStore undefined
Cannot read property ‘createObjectStore’ of undefined
? ? ? ?錯誤原因:???
????????這是因?yàn)閕ndexedDB是異步的,你必須在回調(diào)函數(shù)中使用createObjectStore方法,即使你把createObjectStore調(diào)用寫在open函數(shù)后面,也無法保證哪個先完成。
? ? ? ?6.Failed to execute ‘createObjectStore’
Failed to execute ‘createObjectStore’ on ‘IDBDatabase’: The database is not running a version change transaction.
? ? ? ?錯誤原因:???????????
????????這是由于在success事件的回調(diào)中調(diào)用createObjectStore方法,該方法應(yīng)該在upgradeneeded事件的回調(diào)中調(diào)用。
????????7.stores was not found.
Failed to exectue ‘transaction’ on ‘IDBDatabase’: One of the specified stores was not found.
????????錯誤原因:??????????
????????這是因?yàn)閡pgradeneeded事件沒有被觸發(fā)。
????????這里需要注意upgradeneeded事件。首先,根據(jù)API,應(yīng)該在upgradneeded事件的回調(diào)函數(shù)中調(diào)用createObjectStore方法創(chuàng)建store object,不應(yīng)該在success的回調(diào)中,否則會報(bào)錯。其次,當(dāng)為open方法傳入一個本域沒有的數(shù)據(jù)庫名時,會創(chuàng)建相應(yīng)的數(shù)據(jù)庫,并觸發(fā)success、upgradeneeded事件,從而創(chuàng)建一個store object。但是,chrome54并不會觸發(fā)upgradeneeded事件,造成store object不會被創(chuàng)建,后續(xù)在store object上創(chuàng)建事務(wù)并操作數(shù)據(jù)時候就會報(bào)錯。Stackoverflow上提供的解決辦法是,在open方法傳入第二個參數(shù)(與已有version不同,且更大),這樣就會觸發(fā)chrome上的upgradeneeded事件了。不過,每次都需要調(diào)用db.version獲取當(dāng)前的版本號。
????????8.add出現(xiàn)錯誤
Failed to execute 'add' on 'IDBObjectStore': The transaction has finished.
? ? ? ? 錯誤原因:
????????transaction結(jié)束了,不能繼續(xù)使用,所以才需要每次操作數(shù)據(jù)庫都要獲得一個
其他
????????IDBOpenDBRequest還有一個類似回調(diào)函數(shù)句柄——onupgradeneeded。
????????該句柄在我們請求打開的數(shù)據(jù)庫的版本號和已經(jīng)存在的數(shù)據(jù)庫版本號不一致的時候調(diào)用。
????????indexedDB.open方法還有第二個可選參數(shù),數(shù)據(jù)庫版本號,數(shù)據(jù)庫創(chuàng)建的時候默認(rèn)版本號為1,當(dāng)我們傳入的版本號和數(shù)據(jù)庫當(dāng)前版本號不一致的時候onupgradeneeded就會被調(diào)用,當(dāng)然我們不能試圖打開比當(dāng)前數(shù)據(jù)庫版本低的version.
????????代碼中定義了一個myDB對象,在創(chuàng)建indexedDB request的成功毀掉函數(shù)中,把request獲取的DB對象賦值給了myDB的db屬性,這樣就可以使用myDB.db來訪問創(chuàng)建的indexedDB了。
????????用indexedBD的時候要善用onerror來獲取錯誤的信息,這樣就知道哪里出錯了。
參考文章鏈接:
- 前端indexDB數(shù)據(jù)庫的使用 - 簡書
- HTML5本地?cái)?shù)據(jù)庫--IndexDB的基本操作_ZacheryWu的博客-CSDN博客_indexdb 操作
- indexDB入門_小白目的博客-CSDN博客_indexdb
- IndexedBD的一些心得(總結(jié))_PkJY的博客-CSDN博客
- HTML5-indexedDB使用常見錯誤總結(jié)_柒青衿的博客-CSDN博客
- indexedDB基本使用(內(nèi)含案例)_小小白號的博客-CSDN博客_indexeddb使用
- indexedDB常見坑人錯誤_st紫月的博客-CSDN博客
- indexedDB學(xué)習(xí)小結(jié)_黑月DM的博客-CSDN博客
- indexedDB 小結(jié)_chui62219603的博客-CSDN博客
- indexDB入門到精通,indexdb增刪查改,封裝indexdb類庫,indexdb基本使用_淋雨一直走~的博客-CSDN博客_indexdb
- indexDB出坑指南 | enne5w4
總結(jié)
以上是生活随笔為你收集整理的前端数据库indexedDB入门的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 华盛顿合作规律
- 下一篇: 前端小白如何学习 CSS