日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 前端技术 > HTML >内容正文

HTML

HTML5 API详解(18):IndexedDB 本地存储

發(fā)布時(shí)間:2025/3/15 HTML 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 HTML5 API详解(18):IndexedDB 本地存储 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Web SQL Database實(shí)際上已經(jīng)被廢棄,而HTML5的支持的本地存儲(chǔ)實(shí)際上變成了Local Storage和Session Storage與IndexedDB。Web Storage使用簡(jiǎn)單字符串鍵值對(duì)在本地存儲(chǔ)數(shù)據(jù),方便靈活,但是對(duì)于大量結(jié)構(gòu)化數(shù)據(jù)存儲(chǔ)力不從心,IndexedDB是為了能夠在客戶端存儲(chǔ)大量的結(jié)構(gòu)化數(shù)據(jù),并且使用索引高效檢索的API。

異步API

在IndexedDB大部分操作并不是我們常用的調(diào)用方法,返回結(jié)果的模式,而是請(qǐng)求——響應(yīng)的模式,比如打開數(shù)據(jù)庫(kù)的操作

var request=window.indexedDB.open('testDB');

這條指令并不會(huì)返回一個(gè)DB對(duì)象的句柄,我們得到的是一個(gè)IDBOpenDBRequest對(duì)象,而我們希望得到的DB對(duì)象在其result屬性中,

這條指令請(qǐng)求的響應(yīng)是一個(gè) IDBDatabase對(duì)象,這就是IndexedDB對(duì)象,

除了result,IDBOpenDBRequest接口定義了幾個(gè)重要屬性

  • onerror: 請(qǐng)求失敗的回調(diào)函數(shù)句柄

  • onsuccess:請(qǐng)求成功的回調(diào)函數(shù)句柄

  • onupgradeneeded:請(qǐng)求數(shù)據(jù)庫(kù)版本變化句

創(chuàng)建數(shù)據(jù)庫(kù)

剛才的語(yǔ)句已經(jīng)展示了如何打開一個(gè)indexedDB數(shù)據(jù)庫(kù),調(diào)用indexedDB.open方法就可以創(chuàng)建或者打開一個(gè)indexedDB??匆粋€(gè)完整的處理


function openDB (name) {var request=window.indexedDB.open(name);request.οnerrοr=function(e){console.log('OPen Error!');};request.onsuccess=function(e){myDB.db=e.target.result;};}var myDB={name:'test',version:1,db:null};openDB(myDB.name);


代碼中定義了一個(gè)myDB對(duì)象,在創(chuàng)建indexedDB request的成功毀掉函數(shù)中,把request獲取的DB對(duì)象賦值給了myDB的db屬性,這樣就可以使用myDB.db來訪問創(chuàng)建的indexedDB了。

version

我們注意到除了onerror和onsuccess,IDBOpenDBRequest還有一個(gè)類似回調(diào)函數(shù)句柄——onupgradeneeded。這個(gè)句柄在我們請(qǐng)求打開的數(shù)據(jù)庫(kù)的版本號(hào)和已經(jīng)存在的數(shù)據(jù)庫(kù)版本號(hào)不一致的時(shí)候調(diào)用。

indexedDB.open()方法還有第二個(gè)可選參數(shù),數(shù)據(jù)庫(kù)版本號(hào),數(shù)據(jù)庫(kù)創(chuàng)建的時(shí)候默認(rèn)版本號(hào)為1,當(dāng)我們傳入的版本號(hào)和數(shù)據(jù)庫(kù)當(dāng)前版本號(hào)不一致的時(shí)候onupgradeneeded就會(huì)被調(diào)用,當(dāng)然我們不能試圖打開比當(dāng)前數(shù)據(jù)庫(kù)版本低的version,否則調(diào)用的就是onerror了,修改一下剛才例子


function openDB (name,version) {var version=version || 1;var request=window.indexedDB.open(name,version);request.οnerrοr=function(e){console.log(e.currentTarget.error.message);};request.onsuccess=function(e){myDB.db=e.target.result;};request.onupgradeneeded=function(e){console.log('DB version changed to '+version);};}var myDB={name:'test',version:3,db:null};openDB(myDB.name,myDB.version);


由于剛才已經(jīng)創(chuàng)建了版本為1的數(shù)據(jù)庫(kù),打開版本為3的時(shí)候,會(huì)在控制臺(tái)輸出:DB version changed to 3

關(guān)閉與刪除數(shù)據(jù)庫(kù)

關(guān)閉數(shù)據(jù)庫(kù)可以直接調(diào)用數(shù)據(jù)庫(kù)對(duì)象的close方法

function closeDB(db){db.close();}

刪除數(shù)據(jù)庫(kù)使用indexedDB對(duì)象的deleteDatabase方法

function deleteDB(name){indexedDB.deleteDatabase(name);}

簡(jiǎn)單調(diào)用

var myDB={name:'test',version:3,db:null};openDB(myDB.name,myDB.version);setTimeout(function(){closeDB(myDB.db);deleteDB(myDB.name);},500);

由于異步API愿意,不能保證能夠在closeDB方法調(diào)用前獲取db對(duì)象(實(shí)際上獲取db對(duì)象也比執(zhí)行一條語(yǔ)句慢得多),所以用了setTimeout延遲了一下。當(dāng)然我們注意到每個(gè)indexedDB實(shí)例都有onclose回調(diào)函數(shù)句柄,用以數(shù)據(jù)庫(kù)關(guān)閉的時(shí)候處理,有興趣同學(xué)可以試試,原理很簡(jiǎn)單,不演示了。

object store

有了數(shù)據(jù)庫(kù)后我們自然希望創(chuàng)建一個(gè)表用來存儲(chǔ)數(shù)據(jù),但indexedDB中沒有表的概念,而是objectStore,一個(gè)數(shù)據(jù)庫(kù)中可以包含多個(gè)objectStore,objectStore是一個(gè)靈活的數(shù)據(jù)結(jié)構(gòu),可以存放多種類型數(shù)據(jù)。也就是說一個(gè)objectStore相當(dāng)于一張表,里面存儲(chǔ)的每條數(shù)據(jù)和一個(gè)鍵相關(guān)聯(lián)。

我們可以使用每條記錄中的某個(gè)指定字段作為鍵值(keyPath),也可以使用自動(dòng)生成的遞增數(shù)字作為鍵值(keyGenerator),也可以不指定。選擇鍵的類型不同,objectStore可以存儲(chǔ)的數(shù)據(jù)結(jié)構(gòu)也有差異

鍵類型存儲(chǔ)數(shù)據(jù)
不使用任意值,但是沒添加一條數(shù)據(jù)的時(shí)候需要指定鍵參數(shù)
keyPathJavascript對(duì)象,對(duì)象必須有一屬性作為鍵值
keyGenerator任意值
都使用Javascript對(duì)象,如果對(duì)象中有keyPath指定的屬性則不生成新的鍵值,如果沒有自動(dòng)生成遞增鍵值,填充keyPath指定屬性

事務(wù)

在對(duì)新數(shù)據(jù)庫(kù)做任何事情之前,需要開始一個(gè)事務(wù)。事務(wù)中需要指定該事務(wù)跨越哪些object store。

事務(wù)具有三種模式

  • 只讀:read,不能修改數(shù)據(jù)庫(kù)數(shù)據(jù),可以并發(fā)執(zhí)行

  • 讀寫:readwrite,可以進(jìn)行讀寫操作

  • 版本變更:verionchange

  • var transaction=db.transaction([students','taecher']); //打開一個(gè)事務(wù),使用students 和teacher object store var objectStore=transaction.objectStore('students'); //獲取students object store

    給object store添加數(shù)據(jù)

    調(diào)用數(shù)據(jù)庫(kù)實(shí)例的createObjectStore方法可以創(chuàng)建object store,方法有兩個(gè)參數(shù):store name和鍵類型。調(diào)用store的add方法添加數(shù)據(jù)。有了上面知識(shí),我們可以向object store內(nèi)添加數(shù)據(jù)了

    keyPath

    因?yàn)閷?duì)新數(shù)據(jù)的操作都需要在transaction中進(jìn)行,而transaction又要求指定object store,所以我們只能在創(chuàng)建數(shù)據(jù)庫(kù)的時(shí)候初始化object store以供后面使用,這正是onupgradeneeded的一個(gè)重要作用,修改一下之前代碼

    function openDB (name,version) {var version=version || 1;var request=window.indexedDB.open(name,version);request.οnerrοr=function(e){console.log(e.currentTarget.error.message);};request.onsuccess=function(e){myDB.db=e.target.result;};request.onupgradeneeded=function(e){var db=e.target.result;if(!db.objectStoreNames.contains('students')){db.createObjectStore('students',{keyPath:"id"});}console.log('DB version changed to '+version);};}

    這樣在創(chuàng)建數(shù)據(jù)庫(kù)的時(shí)候我們就為其添加了一個(gè)名為students的object store,準(zhǔn)備一些數(shù)據(jù)以供添加

    var students=[{ id:1001, name:"Byron", age:24 },{ id:1002, name:"Frank", age:30 },{ id:1003, name:"Aaron", age:26 }];



    function addData(db,storeName){var transaction=db.transaction(storeName,'readwrite'); var store=transaction.objectStore(storeName); for(var i=0;i<students.length;i++){store.add(students[i]);}}openDB(myDB.name,myDB.version);setTimeout(function(){addData(myDB.db,'students');},1000);


    這樣我們就在students object store里添加了三條記錄,以id為鍵,在chrome控制臺(tái)看看效果

    keyGenerate

    function openDB (name,version) {var version=version || 1;var request=window.indexedDB.open(name,version);request.οnerrοr=function(e){console.log(e.currentTarget.error.message);};request.onsuccess=function(e){myDB.db=e.target.result;};request.onupgradeneeded=function(e){var db=e.target.result;if(!db.objectStoreNames.contains('students')){db.createObjectStore('students',{autoIncrement: true});}console.log('DB version changed to '+version);};}


    剩下的兩種方式有興趣同學(xué)可以自己摸索一下了

    查找數(shù)據(jù)

    可以調(diào)用object store的get方法通過鍵獲取數(shù)據(jù),以使用keyPath做鍵為例

    function getDataByKey(db,storeName,value){var transaction=db.transaction(storeName,'readwrite'); var store=transaction.objectStore(storeName); var request=store.get(value); request.onsuccess=function(e){ var student=e.target.result; console.log(student.name); }; }

    更新數(shù)據(jù)

    可以調(diào)用object store的put方法更新數(shù)據(jù),會(huì)自動(dòng)替換鍵值相同的記錄,達(dá)到更新目的,沒有相同的則添加,以使用keyPath做鍵為例

    function updateDataByKey(db,storeName,value){var transaction=db.transaction(storeName,'readwrite'); var store=transaction.objectStore(storeName); var request=store.get(value); request.onsuccess=function(e){ var student=e.target.result; student.age=35;store.put(student); }; }

    刪除數(shù)據(jù)及object store

    調(diào)用object store的delete方法根據(jù)鍵值刪除記錄

    function deleteDataByKey(db,storeName,value){var transaction=db.transaction(storeName,'readwrite'); var store=transaction.objectStore(storeName); store.delete(value); }

    調(diào)用object store的clear方法可以清空object store

    function clearObjectStore(db,storeName){var transaction=db.transaction(storeName,'readwrite'); var store=transaction.objectStore(storeName); store.clear(); }

    調(diào)用數(shù)據(jù)庫(kù)實(shí)例的deleteObjectStore方法可以刪除一個(gè)object store,這個(gè)就得在onupgradeneeded里面調(diào)用了

    if(db.objectStoreNames.contains('students')){ db.deleteObjectStore('students'); }


    總結(jié)

    以上是生活随笔為你收集整理的HTML5 API详解(18):IndexedDB 本地存储的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。