IndexedDB存儲(chǔ)數(shù)據(jù)

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ù)的方式媒咳。

indexedDB 的特性

對(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ù)中處理。

幾個(gè)概念

●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ù)表

● IDBTransaction:事務(wù)

● 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);

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末勒叠,一起剝皮案震驚了整個(gè)濱河市兜挨,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌眯分,老刑警劉巖拌汇,帶你破解...
    沈念sama閱讀 212,542評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異弊决,居然都是意外死亡噪舀,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,596評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)丢氢,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)傅联,“玉大人,你說(shuō)我怎么就攤上這事疚察≌糇撸” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 158,021評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵貌嫡,是天一觀的道長(zhǎng)比驻。 經(jīng)常有香客問(wèn)我,道長(zhǎng)岛抄,這世上最難降的妖魔是什么别惦? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,682評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮夫椭,結(jié)果婚禮上掸掸,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好扰付,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,792評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布堤撵。 她就那樣靜靜地躺著,像睡著了一般羽莺。 火紅的嫁衣襯著肌膚如雪实昨。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,985評(píng)論 1 291
  • 那天盐固,我揣著相機(jī)與錄音荒给,去河邊找鬼。 笑死刁卜,一個(gè)胖子當(dāng)著我的面吹牛志电,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蛔趴,決...
    沈念sama閱讀 39,107評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼溪北,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了夺脾?” 一聲冷哼從身側(cè)響起之拨,我...
    開(kāi)封第一講書(shū)人閱讀 37,845評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎咧叭,沒(méi)想到半個(gè)月后蚀乔,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,299評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡菲茬,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,612評(píng)論 2 327
  • 正文 我和宋清朗相戀三年吉挣,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片婉弹。...
    茶點(diǎn)故事閱讀 38,747評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡睬魂,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出镀赌,到底是詐尸還是另有隱情氯哮,我是刑警寧澤,帶...
    沈念sama閱讀 34,441評(píng)論 4 333
  • 正文 年R本政府宣布商佛,位于F島的核電站喉钢,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏良姆。R本人自食惡果不足惜肠虽,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,072評(píng)論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望玛追。 院中可真熱鬧税课,春花似錦闲延、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,828評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至啸如,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間氮惯,已是汗流浹背叮雳。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,069評(píng)論 1 267
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留妇汗,地道東北人帘不。 一個(gè)月前我還...
    沈念sama閱讀 46,545評(píng)論 2 362
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像杨箭,于是被迫代替她去往敵國(guó)和親寞焙。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,658評(píng)論 2 350