在講indexDB之前尤泽,先簡單說說cookie脆淹、localStorage、sessionStorage瘫镇。
cookie
Cookie 是小甜餅的意思鼎兽。顧名思義,cookie 確實非常小铣除,它的大小限制為4KB左右谚咬,是網(wǎng)景公司的前雇員 Lou Montulli 在1993年3月的發(fā)明。它的主要用途有保存登錄信息尚粘,比如你登錄某個網(wǎng)站市場可以看到“記住密碼”择卦,這通常就是通過在 Cookie 中存入一段辨別用戶身份的數(shù)據(jù)來實現(xiàn)的。
localStorage
localStorage 是 HTML5 標準中新加入的技術(shù)郎嫁,它并不是什么劃時代的新東西秉继。早在 IE 6 時代,就有一個叫 userData 的東西用于本地存儲泽铛,而當時考慮到瀏覽器兼容性尚辑,更通用的方案是使用 Flash。而如今盔腔,localStorage 被大多數(shù)瀏覽器所支持杠茬,如果你的網(wǎng)站需要支持 IE6+,那以 userData 作為你的 polyfill 的方案是種不錯的選擇弛随。
sessionStorage
sessionStorage 與 localStorage 的接口類似瓢喉,但保存數(shù)據(jù)的生命周期與 localStorage 不同。 Session 這個詞的意思舀透,直譯過來是“會話”灯荧。它只是可以將一部分數(shù)據(jù)在當前會話中保存下來,刷新頁面數(shù)據(jù)依舊存在盐杂。但當頁面關(guān)閉后逗载,sessionStorage 中的數(shù)據(jù)就會被清空。
Desktop | Chrome | Edge | Firefox | Internet Explorer | Opera | Safari |
---|---|---|---|---|---|---|
localStorage | 4 | Yes | 3.5 | 8 | 10.5 | 4 |
sessionStorage | 5 | Yes | 2 | 8 | 10.5 | 4 |
Mobile | Android webview | Chrome for Android | Edge Mobile | Firefox for Android | Opera for Android | iOS Safari |
---|---|---|---|---|---|---|
localStorage | Yes | Yes | Yes | Yes | 10.5 | 3.2 |
sessionStorage | Yes | Yes | Yes | Yes | 11 | 3.2 |
cookie链烈、localStorage厉斟、sessionStorage異同
特性 | Cookie | localStorage | sessionStorage |
---|---|---|---|
數(shù)據(jù)的生命期 | 一般由服務(wù)器生成,可設(shè)置失效時間强衡。如果在瀏覽器端生成Cookie擦秽,默認是關(guān)閉瀏覽器后失效 | 除非被清除,否則永久保存 | 僅在當前會話下有效,關(guān)閉頁面或瀏覽器后被清除 |
存放數(shù)據(jù)大小 | 4K左右 | 一般為5MB | 一般為5MB |
與服務(wù)器端通信 | 每次都會攜帶在HTTP頭中感挥,如果使用cookie保存過多數(shù)據(jù)會帶來性能問題 | 僅在客戶端(即瀏覽器)中保存缩搅,不參與和服務(wù)器的通信 | 僅在客戶端(即瀏覽器)中保存,不參與和服務(wù)器的通信 |
易用性 | 需要程序員自己封裝触幼,源生的Cookie接口不友好 | 源生接口可以接受硼瓣,亦可再次封裝來對Object和Array有更好的支持 | 源生接口可以接受,亦可再次封裝來對Object和Array有更好的支持 |
接下來就開始上重頭戲了 —— indexDB
indexDB
隨著瀏覽器的功能不斷增強置谦,越來越多的網(wǎng)站開始考慮堂鲤,將大量數(shù)據(jù)儲存在客戶端,這樣可以減少從服務(wù)器獲取數(shù)據(jù)媒峡,直接從本地獲取數(shù)據(jù)瘟栖。
通俗地講,IndexedDB 就是瀏覽器提供的本地數(shù)據(jù)庫谅阿,它可以被網(wǎng)頁腳本創(chuàng)建和操作半哟。IndexedDB 允許儲存大量數(shù)據(jù),提供查找接口签餐,還能建立索引寓涨。這些都是 LocalStorage 所不具備的。就數(shù)據(jù)庫類型而言贱田,IndexedDB 不屬于關(guān)系型數(shù)據(jù)庫(不支持 SQL 查詢語句),更接近 NoSQL 數(shù)據(jù)庫嘴脾。
操作步驟
查看更多信息參考
- 創(chuàng)建/打開數(shù)據(jù)庫男摧。
- 在數(shù)據(jù)庫中創(chuàng)建一個對象倉庫(object store)。
- 啟動一個事務(wù)译打,并發(fā)送一個請求來執(zhí)行一些數(shù)據(jù)庫操作耗拓,像增加或提取數(shù)據(jù)等。
- 通過監(jiān)聽正確類型的 DOM 事件以等待操作完成奏司。
- 在操作結(jié)果上進行一些操作(可以在 request 對象中找到)
打開數(shù)據(jù)庫
var db = null;
var request = window.indexedDB.open("MyTestDatabase");
request.onerror = function(event) {
// 錯誤處理
console.log(' 打開數(shù)據(jù)庫報錯');
};
request.onsuccess = function(event) {
// 成功處理
db = event.target.result;
console.log('打開數(shù)據(jù)庫成功');
};
創(chuàng)建和更新數(shù)據(jù)庫版本號
如果指定的版本號乔询,大于數(shù)據(jù)庫的實際版本號,就會發(fā)生數(shù)據(jù)庫升級事件upgradeneeded韵洋。這時通過事件對象的target.result屬性竿刁,拿到數(shù)據(jù)庫實例。
var db = null;
request.onupgradeneeded = function (event) {
db = event.target.result;
}
新建數(shù)據(jù)庫
新建數(shù)據(jù)庫與打開數(shù)據(jù)庫是同一個操作搪缨。如果指定的數(shù)據(jù)庫不存在食拜,就會新建。不同之處在于副编,后續(xù)的操作主要在upgradeneeded事件的監(jiān)聽函數(shù)里面完成负甸,因為這時版本從無到有,所以會觸發(fā)這個事件。
通常呻待,新建數(shù)據(jù)庫以后打月,第一件事是新建對象倉庫(即新建表)。
request.onupgradeneeded = function(event) {
db = event.target.result;
var objectStore = null;
if (!db.objectStoreNames.contains('imgLists')) {
objectStore = db.createObjectStore('imgLists', { keyPath: 'id' });
// unique name可能會重復
objectStore.createIndex('name', 'name', { unique: false });
}
}
創(chuàng)建一張叫imgLists的表格蚕捉,主鍵是id奏篙。
寫入數(shù)據(jù)
新增數(shù)據(jù)指的是向?qū)ο髠}庫寫入數(shù)據(jù)記錄。這需要通過事務(wù)完成鱼冀。
// new 一個blob對象
var obj1 = {hello: "world"};
var blob = new Blob([JSON.stringify(obj1, null, 2)], {type : 'application/json'});
function add() {
var request = db.transaction(['imgLists'], 'readwrite')
.objectStore('imgLists')
.add({ id: 1, name: '圖片1', path: '/static/image', blob: blob});
request.onsuccess = function (event) {
console.log('數(shù)據(jù)寫入成功');
};
request.onerror = function (event) {
console.log('數(shù)據(jù)寫入失敗');
}
}
查詢數(shù)據(jù)
查詢數(shù)據(jù)也是通過事物完成报破。
function read() {
var transaction = db.transaction(['imgLists']);
var objectStore = transaction.objectStore('imgLists');
// 用戶讀取數(shù)據(jù),參數(shù)是主鍵
var request = objectStore.get(1);
request.onerror = function(event) {
console.log('事務(wù)失敗');
};
request.onsuccess = function( event) {
if (request.result) {
console.log(request.result);
} else {
console.log('未獲得數(shù)據(jù)記錄');
}
};
}
遍歷數(shù)據(jù)
遍歷數(shù)據(jù)表格的所有記錄千绪,要使用指針對象 IDBCursor充易。
function readAll() {
var objectStore = db.transaction('imgLists').objectStore('imgLists');
objectStore.openCursor().onsuccess = function (event) {
var cursor = event.target.result;
if (cursor) {
console.log(cursor);
cursor.continue();
} else {
console.log('沒有更多數(shù)據(jù)了!');
}
};
}
更新數(shù)據(jù)
function update() {
var request = db.transaction(['imgLists'], 'readwrite')
.objectStore('imgLists')
// 主動更新主鍵為1
.put({ id: 1, name: '圖片2', path: '/static/image2'});
request.onsuccess = function (event) {
console.log('數(shù)據(jù)更新成功');
};
request.onerror = function (event) {
console.log('數(shù)據(jù)更新失敗');
}
}
刪除數(shù)據(jù)
function remove() {
var request = db.transaction(['imgLists'], 'readwrite')
.objectStore('imgLists')
.delete(1);
request.onsuccess = function (event) {
console.log('數(shù)據(jù)刪除成功');
};
}
remove();
創(chuàng)建/使用索引
索引的意義在于荸型,可以讓你搜索任意字段盹靴,也就是說從任意字段拿到數(shù)據(jù)記錄。如果不建立索引瑞妇,默認只能搜索主鍵(即從主鍵取值)稿静。
objectStore.createIndex('name', 'name', { unique: false });
function findIndex() {
var transaction = db.transaction(['imgLists'], 'readonly');
var store = transaction.objectStore('imgLists');
var index = store.index('name');
var request = index.get('圖片1');
request.onsuccess = function (e) {
var result = e.target.result;
if (result) {
console.log(result);
} else {
// ...
}
}
}
使用場景
indexDB是一個瀏覽器使用簡易的數(shù)據(jù)庫。隨著前端功能復雜度提升辕狰,用戶需要多元化改备,前端indexDB應用也就越來越多。桌面應用蔓倍、Progressive Web App(PWA)悬钳、chrome擴展組件的開發(fā)等。用戶同時會獲取/操作更多的信息偶翅,怎么留存這些大量的數(shù)據(jù)默勾,那么我們的indexDB就上線了。案例:DevDocs聚谁,electron開發(fā)的桌面應用(圖片傳輸)母剥。