IndexedDB 是一個(gè)基于 JavaScript 的面向?qū)ο蟮氖聞?wù)型數(shù)據(jù)庫(kù)凿菩。有了LocalStorage和Cookies,為什么還要推出indexedDB呢密强?其實(shí)對(duì)于在瀏覽器里存儲(chǔ)數(shù)據(jù)疙驾,可以使用cookies或LocalStorage,但它們都是比較簡(jiǎn)單的技術(shù)碌尔,而IndexedDB提供了類(lèi)似數(shù)據(jù)庫(kù)風(fēng)格的數(shù)據(jù)存儲(chǔ)和使用方式。
LocalStorage 與 IndexedDB 區(qū)別也適用場(chǎng)景
LocalStorage是用key-value鍵值模式存儲(chǔ)數(shù)據(jù)券敌,它存儲(chǔ)的數(shù)據(jù)都是字符串形式唾戚。如果你想讓LocalStorage存儲(chǔ)對(duì)象,你需要借助JSON.stringify()能將對(duì)象變成字符串形式待诅,再用JSON.parse()將字符串還原成對(duì)象,就是專門(mén)為小數(shù)量數(shù)據(jù)設(shè)計(jì)的叹坦,所以它的 api 設(shè)計(jì)為同步的。
IndexedDB很適合存儲(chǔ)大量數(shù)據(jù)卑雁,它的 API 是異步調(diào)用的募书。IndexedDB使用索引存儲(chǔ)數(shù)據(jù)绪囱,各種數(shù)據(jù)庫(kù)操作放在事務(wù)中執(zhí)行。IndexedDB甚至還支持簡(jiǎn)單的數(shù)據(jù)類(lèi)型莹捡。IndexedDB比localstorage強(qiáng)大得多鬼吵,但它的 API 也相對(duì)復(fù)雜。對(duì)于簡(jiǎn)單的數(shù)據(jù)道盏,你應(yīng)該繼續(xù)使用localstorage而柑,但當(dāng)你希望存儲(chǔ)大量數(shù)據(jù)時(shí),IndexedDB會(huì)明顯的更適合荷逞,IndexedDB能提供你更為復(fù)雜的查詢數(shù)據(jù)的方式媒咳。
對(duì)象倉(cāng)庫(kù)
有了數(shù)據(jù)庫(kù)后我們自然希望創(chuàng)建一個(gè)表用來(lái)存儲(chǔ)數(shù)據(jù),但 indexedDB 中沒(méi)有表的概念种远,而是 objectStore涩澡,一個(gè)數(shù)據(jù)庫(kù)中可以包含多個(gè) objectStore,objectStore 是一個(gè)靈活的數(shù)據(jù)結(jié)構(gòu)坠敷,可以存放多種類(lèi)型數(shù)據(jù)妙同。也就是說(shuō)一個(gè) objectStore 相當(dāng)于一張表,里面存儲(chǔ)的每條數(shù)據(jù)和一個(gè)鍵相關(guān)聯(lián)膝迎。我們可以使用每條記錄中的某個(gè)指定字段作為鍵值(keyPath)粥帚,也可以使用自動(dòng)生成的遞增數(shù)字作為鍵值(keyGenerator),也可以不指定限次。選擇鍵的類(lèi)型不同芒涡,objectStore 可以存儲(chǔ)的數(shù)據(jù)結(jié)構(gòu)也有差異。
事務(wù)性
在 indexedDB 中卖漫,每一個(gè)對(duì)數(shù)據(jù)庫(kù)操作是在一個(gè)事務(wù)的上下文中執(zhí)行的费尽。事務(wù)范圍一次影響一個(gè)或多個(gè) object stores,你通過(guò)傳入一個(gè) object store 名字的數(shù)組到創(chuàng)建事務(wù)范圍的函數(shù)來(lái)定義羊始。例如:db.transaction(storeName, 'readwrite')旱幼,創(chuàng)建事務(wù)的第二個(gè)參數(shù)是事務(wù)模式。當(dāng)請(qǐng)求一個(gè)事務(wù)時(shí),必須決定是按照只讀還是讀寫(xiě)模式請(qǐng)求訪問(wèn)突委。
基于請(qǐng)求
對(duì) indexedDB 數(shù)據(jù)庫(kù)的每次操作柏卤,描述為通過(guò)一個(gè)請(qǐng)求打開(kāi)數(shù)據(jù)庫(kù),訪問(wèn)一個(gè) object store,再繼續(xù)匀油。IndexedDB API 天生是基于請(qǐng)求的,這也是 API 異步本性指示缘缚。對(duì)于你在數(shù)據(jù)庫(kù)執(zhí)行的每次操作,你必須首先為這個(gè)操作創(chuàng)建一個(gè)請(qǐng)求。當(dāng)請(qǐng)求完成,你可以響應(yīng)由請(qǐng)求結(jié)果產(chǎn)生的事件和錯(cuò)誤钧唐。
異步
在 IndexedDB 大部分操作并不是我們常用的調(diào)用方法忙灼,返回結(jié)果的模式匠襟,而是請(qǐng)求—響應(yīng)的模式亭敢,所謂異步 API 是指并不是這條指令執(zhí)行完畢望薄,我們就可以使用 request.result 來(lái)獲取 indexedDB 對(duì)象了披摄,就像使用 ajax 一樣,語(yǔ)句執(zhí)行完并不代表已經(jīng)獲取到了對(duì)象里初,所以我們一般在其回調(diào)函數(shù)中處理。
●IDBFactory:數(shù)據(jù)庫(kù)工廠忽舟,負(fù)責(zé)打開(kāi)或者創(chuàng)建數(shù)據(jù)庫(kù)
????●IDBFactory.open 方法發(fā)送一個(gè)打開(kāi)或者創(chuàng)建一個(gè)數(shù)據(jù)庫(kù)的請(qǐng)求
????●IDBFactory.deleteDatabase 方法: 發(fā)送一個(gè)刪除數(shù)據(jù)庫(kù)的請(qǐng)求
●IDBDatabase: 數(shù)據(jù)庫(kù)
????●IDBDatabase.close 方法關(guān)閉數(shù)據(jù)庫(kù)双妨。
????●IDBDatabase.createObjectStore 方法創(chuàng)建 store,相當(dāng)于表
????● IDBDatabase.transaction 開(kāi)啟一個(gè)事務(wù)叮阅。
● IDBIndex:數(shù)據(jù)庫(kù)表的索引
● IDBObjectStore:數(shù)據(jù)庫(kù)表
● IDBRequest:機(jī)會(huì)是所有 indexedDB 操作的返回值刁品,indexedDB 操作請(qǐng)求
????● IDBRequest.result 結(jié)果
????● IDBRequest.onerror 異常事件
????● IDBRequest.onsuccess 成功的事件
function IndexedDBDataBase(){
? ? var myDB={
? ? ? ? ????name:'TestDatabase',
? ? ? ? ????version:1,
? ? ? ????? db:null,
? ? ? ? ????ojstore:{
? ? ? ? ? ? ????name:'user',//存儲(chǔ)空間表的名字
? ? ? ? ? ? ????keypath:'id'//主鍵
? ? ? ????? }
? ? };
? ? var userObject=null;
// 創(chuàng)建indexedDB對(duì)象,兼容各種瀏覽器
? ? var indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.msIndexedDB;
? ? var IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange;//鍵范圍
? ? if (!indexedDB) {
? ? ? console.log("你的瀏覽器不支持IndexedDB");
? ? }
? ? this.getDataBaseObject= function(){
? ? ? ? ? ? //獲取數(shù)據(jù)庫(kù)信息
? ? ? ? ? ? ? return myDB;
? ? ? ? }
? ? this.getUserObject= function(){
? ? ? ? ? ? //獲取數(shù)據(jù)庫(kù)信息
? ? ? ? ? ? ? return userObject;
? ? ? ? }
? ? /*? 建立或打開(kāi)數(shù)據(jù)庫(kù)浩姥,建立對(duì)象存儲(chǔ)空間(ObjectStore)
? ? * @param {string}echo3991Type 版本類(lèi)型
? ? * @param {obj}
? ? * @param {bool}
? ? * @param {bool}
? ? */
? ? this.openDB = function (myDB,dbname,dbversion,callback){
? ? ? ? ? ? var self = this;
? ? ? ? ? ? var version = dbversion || 1;
? ? ? ? ? ? var request = indexedDB.open(dbname,version);
? ? ? ? ? ? request.onerror = function(e){
? ? ? ? ? ? ? ? console.log(e.currentTarget.error.message);
? ? ? ? ? ? };
? ? ? ? ? ? request.onsuccess = function(e){
? ? ? ? ? ? ? ? myDB.db = e.target.result;
? ? ? ? ? ? ? ? console.log('成功建立并打開(kāi)數(shù)據(jù)庫(kù):'+myDB.name+' version'+dbversion);
? ? ? ? ? ? };
? ? ? ? ? ? request.onupgradeneeded=function(e){
? ? ? ? ? ? ? ? var db=e.target.result,transaction= e.target.transaction,store;
? ? ? ? ? ? ? ? if(!db.objectStoreNames.contains(myDB.ojstore.name)){
? ? ? ? ? ? ? ? ? ? //沒(méi)有該對(duì)象空間時(shí)創(chuàng)建該對(duì)象空間
? ? ? ? ? ? ? ? ? ? store = db.createObjectStore(myDB.ojstore.name,{keyPath:myDB.ojstore.keypath});
? ? ? ? ? ? ? ? ? ? console.log('成功建立對(duì)象存儲(chǔ)空間:'+myDB.ojstore.name);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? },
/*? 刪除數(shù)據(jù)庫(kù)
? ? * @param {string}echo3991Type 版本類(lèi)型
? ? * @param {obj}
? ? * @param {bool}
? ? * @param {bool}
? ? */
? ? this.deletedb = function(dbname){
? ? ? ? ? ? //刪除數(shù)據(jù)庫(kù)
? ? ? ? ? ? var self = this;
? ? ? ? ? ? self.indexedDB.deleteDatabase(dbname);
? ? ? ? ? ? console.log(dbname+'數(shù)據(jù)庫(kù)已刪除')
? ? ? ? },
? ? ? ? this.closeDB= function(db){
? ? ? ? ? ? //關(guān)閉數(shù)據(jù)庫(kù)
? ? ? ? ? ? db.close();
? ? ? ? ? ? console.log('數(shù)據(jù)庫(kù)已關(guān)閉')
? ? ? ? }
? ? ? this.addData= function(db,storename,data){
? ? ? ? ? ? //添加數(shù)據(jù)挑随,重復(fù)添加會(huì)報(bào)錯(cuò)
? ? ? ? ? ? var store = store = db.transaction(storename,'readwrite').objectStore(storename),request;
? ? ? ? ? ? for(var i = 0 ; i < data.length;i++){
? ? ? ? ? ? ? ? request = store.add(data[i]);
? ? ? ? ? ? ? ? request.onerror = function(){
? ? ? ? ? ? ? ? ? ? console.error('add添加數(shù)據(jù)庫(kù)中已有該數(shù)據(jù)')
? ? ? ? ? ? ? ? };
? ? ? ? ? ? ? ? request.onsuccess = function(){
? ? ? ? ? ? ? ? ? ? console.log('add添加數(shù)據(jù)已存入數(shù)據(jù)庫(kù)')
? ? ? ? ? ? ? ? };
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? this.putData= function(db,storename,data){
? ? ? ? ? ? //添加數(shù)據(jù),重復(fù)添加會(huì)更新原有數(shù)據(jù)
? ? ? ? ? ? var store = store = db.transaction(storename,'readwrite').objectStore(storename),request;
? ? ? ? ? ? for(var i = 0 ; i < data.length;i++){
? ? ? ? ? ? ? ? request = store.put(data[i]);
? ? ? ? ? ? ? ? request.onerror = function(){
? ? ? ? ? ? ? ? ? ? console.error('put添加數(shù)據(jù)庫(kù)中已有該數(shù)據(jù)')
? ? ? ? ? ? ? ? };
? ? ? ? ? ? ? ? request.onsuccess = function(){
? ? ? ? ? ? ? ? ? ? console.log('put添加數(shù)據(jù)已存入數(shù)據(jù)庫(kù)')
? ? ? ? ? ? ? ? };
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? this.getDataByKey= function(db,storename,key){
? ? ? ? ? ? //根據(jù)存儲(chǔ)空間的鍵找到對(duì)應(yīng)數(shù)據(jù)
? ? ? ? ? ? var store = db.transaction(storename,'readwrite').objectStore(storename);
? ? ? ? ? ? var request = store.get(key);
? ? ? ? ? ? request.onerror = function(){
? ? ? ? ? ? ? ? console.error('getDataByKey error');
? ? ? ? ? ? };
? ? ? ? ? ? request.onsuccess = function(e){
? ? ? ? ? ? ? ? var result = e.target.result;
? ? ? ? ? ? ? ? userObject= result;
? ? ? ? ? ? ? ? console.log('查找數(shù)據(jù)成功')
? ? ? ? ? ? ? ? console.log(result);
? ? ? ? ? ? };
? ? ? ? }
? ? ? ? this.deleteData= function(db,storename,key){
? ? ? ? ? ? //刪除某一條記錄
? ? ? ? ? ? var store = store = db.transaction(storename,'readwrite').objectStore(storename);
? ? ? ? ? ? store.delete(key)
? ? ? ? ? ? console.log('已刪除存儲(chǔ)空間'+storename+'中'+key+'記錄');
? ? ? ? }
? ? ? ? this.clearData= function(db,storename){
? ? ? ? ? ? //刪除存儲(chǔ)空間全部記錄
? ? ? ? ? ? var store = db.transaction(storename,'readwrite').objectStore(storename);
? ? ? ? ? ? store.clear();
? ? ? ? ? ? console.log('已刪除存儲(chǔ)空間'+storename+'全部記錄');
? ? ? ? }
? ? }
調(diào)用方法:
var user=[{
? ? ? ? ? ? ? ? ? ? ? ? id:1,
? ? ? ? ? ? ? ? ? ? ? ? name:user_name,
? ? ? ? ? ? ? ? ? ? ? ? is_admin:data.is_admin,
? ? ? ? ? ? ? ? ? ? ? ? password:password
? ? ? ? ? ? ? ? ? ? }];
? ? ? ? ? ? ? ? ? ? console.log(user)
? ? ? ? ? ? ? ? ? ? var myDB=IndexedDBD.getDataBaseObject();
? ? ? ? ? ? ? ? ? ? IndexedDBD.openDB(myDB,myDB.name,myDB.version);
? ? ? ? ? ? ? ? ? ? setTimeout(function(){
? ? ? ? ? ? ? ? ? ? ? ? var myDB=IndexedDBD.getDataBaseObject();
? ? ? ? ? ? ? ? ? ? ? ? setTimeout(function(){
? ? ? ? ? ? ? ? ? ? ? ? ? IndexedDBD.addData(myDB.db,myDB.ojstore.name,user);
? ? ? ? ? ? ? ? ? ? ? ? },200);
? ? ? ? ? ? ? ? ? ? },500);