HTML5本地存儲 localStorage 、sessionStorage、WebSQL、indexedDB

隨著移動網絡的興起,WebApp也不在是新的話題了,以前Web與App原生系統最大3個差別在于:

  • 用戶體驗,主要涉及到操作的平滑性,軟件整體的性能。
  • 本地存儲能力,原生App能很好的發揮本地存儲的能力,將不常更新的數據長期存儲在本地。
  • 操作系統資源,原生App能很好操作其他的app,最為常見的功能是共享到微信朋友圈。

這幾年WebApp一直在想辦法攻克這些難關,上述兩個問題在隨著技術的不斷升級也有了很好的改觀,對于用戶體驗,目前SPA(單頁面)框架如:React、VUE、Angular都能很好的實現,配合著HTML5的離線緩存技術,讓WebApp操作更加的平滑。那么對于本地存儲來說,也有了很好的突破。本文將針對本地存儲介紹一下HTML5時代帶來的本地化存儲技術, localStorage 、sessionStorage、WebSQL、indexedDB等。

1. localStorage與sessionStorage

localstorage、sessionStorage是瀏覽器家族最早支持的本地緩存。它們的有什么區別呢?

  • localStorage 用于持久化的本地存儲,除非主動刪除數據,否則數據是永遠不會過期的。
  • sessionStorage 用于本地存儲一個會話(session)中的數據,這些數據只有在同一個會話中的頁面才能訪問并且當會話結束后數據也隨之銷毀。因此sessionStorage不是一種持久化的本地存儲,僅僅是會話級別的存儲。

1.1 web storage(localStorage和sessionStorage)和cookie的區別

Web Storage的概念和cookie相似,區別是它是為了更大容量存儲設計的。Cookie的大小是受限的,并且每次你請求一個新的頁面的時候Cookie都會被發送過去,這樣無形中浪費了帶寬,另外cookie還需要指定作用域,不可以跨域調用。除此之外,Web Storage擁有setItem,getItem,removeItem,clear等方法,不像cookie需要前端開發者自己封裝setCookie,getCookie。但是Cookie也是不可以或缺的:Cookie的作用是與服務器進行交互,作為HTTP規范的一部分而存在 ,而Web Storage僅僅是為了在本地“存儲”數據而生。

各個瀏覽器對于Web Storage存儲量大致如下(單位字節):
IE 9 > 4999995 + 5 = 5000000
firefox 22.0 > 5242875 + 5 = 5242880
chrome 28.0 > 2621435 + 5 = 2621440
safari 5.1 > 2621435 + 5 = 2621440
opera 12.15 > 5M (超出則會彈出允許請求更多空間的對話框)

1.2 html5 web storage的瀏覽器支持情況

瀏覽器的支持除了IE7及以下不支持外,其他標準瀏覽器都完全支持(ie及FF需在web服務器里運行)。

1.3 localStorage和sessionStorage操作

localStorage和sessionStorage都具有相同的操作方法,例如setItem、getItem和removeItem等

  1. setItem存儲value
    用途:將value存儲到key字段用法:.setItem( key, value)代碼示例:
sessionStorage.setItem("key", "value"); 
localStorage.setItem("site", "js8.in");
  1. getItem獲取value
    用途:獲取指定key本地存儲的值用法:.getItem(key)代碼示例:
var value = sessionStorage.getItem("key"); 
var site = localStorage.getItem("site");
  1. removeItem刪除key
    用途:刪除指定key本地存儲的值用法:.removeItem(key)代碼示例:
sessionStorage.removeItem("key"); 
localStorage.removeItem("site");
  1. clear清除所有的key/value
    用途:清除所有的key/value用法:.clear()代碼示例:
sessionStorage.clear(); 
localStorage.clear();
  1. 其他操作方法:點操作和[]
    web Storage不但可以用自身的setItem,getItem等方便存取,也可以像普通對象一樣用點(.)操作符,及[]的方式進行數據存儲,像如下的代碼:
var storage = window.localStorage; 
storage.key1 = "hello"; 
storage["key2"] = "world"; 
console.log(storage.key1); console.log(storage["key2"]);
  1. localStorage和sessionStorage的key和length屬性實現遍歷
    sessionStorage和localStorage提供的key()和length可以方便的實現存儲的數據遍歷,例如下面的代碼:
var storage = window.localStorage; 
for (var i=0, len = storage.length; i < len; i++){ 
        var key = storage.key(i); 
        var value = storage.getItem(key); 
        console.log(key + "=" + value); 
}

注意事項:localStorage和sessionStorage只支持字符串的數據存儲,不能存儲javascript的對象以及數據流等數據。

2.WebSQL與indexedDB

WebSQL和IndexedDB是最新的HTML5本地緩存技術,擁有著比localStorage和sessionStorage更強大的功能,WebSQL和IndexedDB可以存儲更多類型的數據,如數據流,圖片,視頻等。由于WebSQL在瀏覽器的支持沒有IndexedDB好,所以本文主要介紹IndexedDB.

2.1 IndexedDB

IndexedDB 是一種可以讓你在用戶的瀏覽器內持久化存儲數據的方法。特點如下:

  • 支持事務、游標、索引等數據庫操作
  • 一般瀏覽器會分配50M-250M不等的內存
  • 持久化存儲,清除瀏覽器緩存不會被刪除(localStorage是會被刪除的)
  • 支持多種數據格式:arrayBuffer、String、Object、Array、File、Blob、ImageData都ok
  • 不支持跨域,一個域可以有多個數據庫
  • 開發中需要謹記的一個特性:異步操作,換句話說,所有操作都需要在回調函數中完成
  • 存儲空間大,IndexedDB的存儲空間比localStorage大得多,一般來說不少于250MB。IE的儲存上限是250MB,Chrome和Opera是硬盤剩余空間的某個百分比,Firefox則沒有上限。

2.2 IndexedDB兼容性

前端在學一項技術時候,往往先關注它的兼容性,再牛的技術,不兼容也是用不到項目中的。


這是can i use中指示的情況,我實測的結果是: * PC端chrome 54上有特殊表現(在第一次打開indexedDB時,upgradeneeded事件不觸發),firfox表現正常 * 移動端ios8-ios10 safari支持,但是X5內核不支持;Android上X5內核支持

2.3 IndexedDB使用

IndexedDB在使用上需要調用HTML5提供的API,過程略有些麻煩。因此本文推薦一個工具類:localForage,這個工具類庫是firefox公司開發和維護的開源類庫。封裝了WebSQL、IndexedDB以及localstorage三種存儲模式的API,讓使用者更好的來選擇存儲模式。然而它對外釋放的API是統一的,簡單的。
簡單對比一下IndexedDB原生API和localForage的API的使用方法,代碼如下:
IndexedDB原生API

// IndexedDB.
var db;
var dbName = "dataspace";
var users = [ {id: 1, fullName: 'Matt'}, {id: 2, fullName: 'Bob'} ];
var request = indexedDB.open(dbName, 2);
request.onerror = function(event) {
    // 錯誤處理
};
request.onupgradeneeded = function(event) {
    db = event.target.result;
    var objectStore = db.createObjectStore("users", { keyPath: "id" });
    objectStore.createIndex("fullName", "fullName", { unique: false });
    objectStore.transaction.oncomplete = function(event) {
        var userObjectStore = db.transaction("users", "readwrite").objectStore("users");
    }
};
  
var transaction = db.transaction(["users"], "readwrite");
// 所有數據都添加到數據后調用
transaction.oncomplete = function(event) {
    console.log("All done!");
};
transaction.onerror = function(event) {
    // 錯誤處理
};
  
var objectStore = transaction.objectStore("users");
for (var i in users) {
    var request = objectStore.add(users[i]);
    request.onsuccess = function(event) {
        // 里面包含我們需要的用戶信息
        console.log(event.target.result);
    };
}

localForage API實現

// 保存用戶信息
var users = [ {id: 1, fullName: 'Matt'}, {id: 2, fullName: 'Bob'} ];
localForage.setItem('users', users, function(result) {
    console.log(result);
});

是不是簡單了很多?下面針對localForage的使用做一下詳細的介紹。

3.localForage的使用 API 地址

localForage的使用非常簡單,在使用前需要進行一個配置工作,當然也可以不做配置工作。在不做配置的時候,localForage默認使用IndexedDB作為存儲模式。通過查看localForage的源碼來看看配置的缺省值吧,代碼如下:

//默認的驅動順序,首選是IndexedDB,其次是WebSQL,最后是Localstorage
var DefaultDriverOrder = [
    DriverType.INDEXEDDB
   ,DriverType.WEBSQL
   ,DriverType.LOCALSTORAGE
];

//對外釋放的方法api
var LibraryMethods = [
  'clear'
  ,'getItem'
  ,'iterate'
  ,'key'
  ,'keys'
  ,'length'
  ,'removeItem'
  ,'setItem'
];

//默認的配置
var DefaultConfig = {
    description: '',
    driver: DefaultDriverOrder.slice(),
    name: 'localforage',//默認數據庫名稱
    size: 4980736,//目前只支持WebSQL可以設置大小
    storeName: 'keyvaluepairs',
    version: 1.0
};

3.1 Config 配置方法

可以通過Config方法來設置默認的值,如驅動、數據庫名稱、數據集合名稱、存儲大小等。詳細內容如下:

屬性 默認值 描述
driver [localforage.INDEXEDDB,localforage.WEBSQL,localforage.LOCALSTORAGE] 要使用的首選驅動程序。 格式與傳遞給setDriver的格式相同
name localforage 數據庫名稱
size 4980736(字節) 數據庫的大小,目前只有WebSQL才有效
storeName keyvaluepairs 集合名稱
version 1.0 數據庫的版本號
description 空字符串 數據庫的描述,基本上用于開發人員的使用

例子如下:

// This will rename the database from "localforage"
// to "Hipster PDA App".
localforage.config({
    name: 'Hipster PDA App'
});

// This will force localStorage as the storage
// driver even if another is available. You can
// use this instead of `setDriver()`.
localforage.config({
    driver: localforage.LOCALSTORAGE,
    name: 'I-heart-localStorage'
});

// This will use a different driver order.
localforage.config({
    driver: [localforage.WEBSQL,
             localforage.INDEXEDDB,
             localforage.LOCALSTORAGE],
    name: 'WebSQL-Rox'
});

3.2 getItem 方法

從存儲庫獲取項目,并將結果提供給回調。 如果鍵不存在,getItem()將返回null。

getItem(key, successCallback)

例子如下:


//promise方式
localforage.getItem('somekey').then(function(value) {
    // This code runs once the value has been loaded
    // from the offline store.
    console.log(value);
}).catch(function(err) {
    // This code runs if there were any errors
    console.log(err);
});

// Callback方式
localforage.getItem('somekey', function(err, value) {
    // Run this code once the value has been
    // loaded from the offline store.
    console.log(value);
});

3.3 setItem 方法

將數據保存到離線數據庫

setItem(key, value, successCallback)

例子如下:

localforage.setItem('somekey', 'some value').then(function (value) {
    // Do other things once the value has been saved.
    console.log(value);
}).catch(function(err) {
    // This code runs if there were any errors
    console.log(err);
});

// Unlike localStorage, you can store non-strings.
localforage.setItem('my array', [1, 2, 'three']).then(function(value) {
    // This will output `1`.
    console.log(value[0]);
}).catch(function(err) {
    // This code runs if there were any errors
    console.log(err);
});

// You can even store binary data from an AJAX request.
req = new XMLHttpRequest();
req.open('GET', '/photo.jpg', true);
req.responseType = 'arraybuffer';

req.addEventListener('readystatechange', function() {
    if (req.readyState === 4) { // readyState DONE
        localforage.setItem('photo', req.response).then(function(image) {
            // This will be a valid blob URI for an <img> tag.
            var blob = new Blob([image]);
            var imageURI = window.URL.createObjectURL(blob);
        }).catch(function(err) {
          // This code runs if there were any errors
          console.log(err);
        });
    }
});

3.4 removeItem方法

根據key刪除數據的方法
例子如下:

localforage.removeItem('somekey').then(function() {
    // Run this code once the key has been removed.
    console.log('Key is cleared!');
}).catch(function(err) {
    // This code runs if there were any errors
    console.log(err);
});

3.5 clear 方法

清空數據的方法
例子如下:

localforage.clear().then(function() {
    // Run this code once the database has been entirely deleted.
    console.log('Database is now empty.');
}).catch(function(err) {
    // This code runs if there were any errors
    console.log(err);
});

3.6 其他方法

還有length、key、keys、iterate等方法,請詳見 API

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,546評論 6 533
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,570評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,505評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,017評論 1 313
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,786評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,219評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,287評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,438評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,971評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,796評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,995評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,540評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,230評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,662評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,918評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,697評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,991評論 2 374

推薦閱讀更多精彩內容