Web存儲(chǔ)方案

如何選擇?

客戶端存儲(chǔ)無(wú)非就是 Cookie、SessionStorage、LocalStorage、IndexedDB、WebSQL 這些,從一定程度上來(lái)說(shuō)怎么存儲(chǔ)都是可以的,只是你覺(jué)得怎么方便,就怎么存儲(chǔ)

Cookie

HTTP Cookie(也叫 Web Cookie 或?yàn)g覽器 Cookie)是服務(wù)器發(fā)送到用戶瀏覽器并保存在本地的一小塊數(shù)據(jù),它會(huì)在瀏覽器下次向同一服務(wù)器再發(fā)起請(qǐng)求時(shí)被攜帶并發(fā)送到服務(wù)器上。通常,它用于告知服務(wù)端兩個(gè)請(qǐng)求是否來(lái)自同一瀏覽器,如保持用戶的登錄狀態(tài)。

Cookie 主要用于以下三個(gè)方面:

  • 會(huì)話狀態(tài)管理(如用戶登錄狀態(tài)、購(gòu)物車、游戲分?jǐn)?shù)或其它需要記錄的信息);
  • 個(gè)性化設(shè)置(如用戶自定義設(shè)置、主題等);
  • 瀏覽器行為跟蹤(如跟蹤分析用戶行為等)。

Cookie 的特點(diǎn):

  • Cookie 的大小受限,一般為 4 KB;
  • 同一個(gè)域名下存放 Cookie 的個(gè)數(shù)是有限制的,不同瀏覽器的個(gè)數(shù)不一樣,一般為 20 個(gè);
  • Cookie 支持設(shè)置過(guò)期時(shí)間,當(dāng)過(guò)期時(shí)自動(dòng)銷毀;
  • 每次發(fā)起同域下的 HTTP 請(qǐng)求時(shí),都會(huì)攜帶當(dāng)前域名下的 Cookie;
  • 支持設(shè)置為 HttpOnly,防止 Cookie 被客戶端的 JavaScript 訪問(wèn)。
// 簡(jiǎn)單用法
document.cookie = "name=semlinker";
document.cookie = "favorite_food=tripe";

alert(document.cookie);
// 顯示: name=semlinker;favorite_food=tripe

localStorage

一種持久化的存儲(chǔ)方式,也就是說(shuō)如果不手動(dòng)清除,數(shù)據(jù)就永遠(yuǎn)不會(huì)過(guò)期。它是采用鍵值對(duì)的方式存儲(chǔ)數(shù)據(jù),按域名將數(shù)據(jù)分別保存到對(duì)應(yīng)數(shù)據(jù)庫(kù)文件里。相比 Cookie 來(lái)說(shuō),它能保存更大的數(shù)據(jù)。

localStorage 的特點(diǎn):

  • 大小限制為 5MB ~10MB;
  • 在同源的所有標(biāo)簽頁(yè)和窗口之間共享數(shù)據(jù);
  • 數(shù)據(jù)僅保存在客戶端,不與服務(wù)器進(jìn)行通信;
  • 數(shù)據(jù)持久存在且不會(huì)過(guò)期,重啟瀏覽器后仍然存在;對(duì)數(shù)據(jù)的操作是同步的。
// 通過(guò)setItem()增加一個(gè)數(shù)據(jù)項(xiàng)
localStorage.setItem('myName', 'Semlinker');

// 通過(guò)getItem()獲取某個(gè)數(shù)據(jù)項(xiàng)
let me = localStorage.getItem('myName');

// 通過(guò)removeItem()移除某個(gè)數(shù)據(jù)項(xiàng)
localStorage.removeItem('myName');

// 移除所有數(shù)據(jù)項(xiàng)
localStorage.clear();

sessionStorage

與服務(wù)端的 session 類似,sessionStorage 是一種會(huì)話級(jí)別的緩存,關(guān)閉瀏覽器時(shí)數(shù)據(jù)會(huì)被清除。需要注意的是 sessionStorage 的作用域是窗口級(jí)別的,也就是說(shuō)不同窗口之間保存的 sessionStorage 數(shù)據(jù)是不能共享的。

sessionStorage 的特點(diǎn):

  • sessionStorage 的數(shù)據(jù)只存在于當(dāng)前瀏覽器的標(biāo)簽頁(yè);
  • 數(shù)據(jù)在頁(yè)面刷新后依然存在,但在關(guān)閉瀏覽器標(biāo)簽頁(yè)之后數(shù)據(jù)就會(huì)被清除;
  • 與 localStorage 擁有統(tǒng)一的 API 接口;
  • 對(duì)數(shù)據(jù)的操作是同步的。
// 通過(guò)setItem()增加一個(gè)數(shù)據(jù)項(xiàng)
sessionStorage.setItem('myName', 'Semlinker');

// 通過(guò)getItem()獲取某個(gè)數(shù)據(jù)項(xiàng)
let me = sessionStorage.getItem('myName');

// 通過(guò)removeItem()移除某個(gè)數(shù)據(jù)項(xiàng)
sessionStorage.removeItem('myName');

// 移除所有數(shù)據(jù)項(xiàng)
sessionStorage.clear();

IndexedDB

IndexedDB 是一種底層 API,用于客戶端存儲(chǔ)大量結(jié)構(gòu)化數(shù)據(jù),包括文件、二進(jìn)制大型對(duì)象。該 API 使用索引來(lái)實(shí)現(xiàn)對(duì)該數(shù)據(jù)的高性能搜索。雖然 Web Storage 對(duì)于存儲(chǔ)較少量的數(shù)據(jù)很有用,但對(duì)于存儲(chǔ)更大量的結(jié)構(gòu)化數(shù)據(jù)來(lái)說(shuō),這種方法不太好用。IndexedDB 提供了一個(gè)解決方案。

IndexedDB 的特點(diǎn):

  • 存儲(chǔ)空間大:存儲(chǔ)空間可以達(dá)到幾百兆甚至更多;
  • 支持二進(jìn)制存儲(chǔ):它不僅可以存儲(chǔ)字符串,而且還可以存儲(chǔ)二進(jìn)制數(shù)據(jù);
  • IndexedDB 有同源限制,每一個(gè)數(shù)據(jù)庫(kù)只能在自身域名下能訪問(wèn),不能跨域名訪問(wèn);
  • 支持事務(wù)型:IndexedDB 執(zhí)行的操作會(huì)按照事務(wù)來(lái)分組的,在一個(gè)事務(wù)中,要么所有的操作都成功,要么所有的操作都失??;
  • 鍵值對(duì)存儲(chǔ):IndexedDB 內(nèi)部采用對(duì)象倉(cāng)庫(kù)(object store)存放數(shù)據(jù)。所有類型的數(shù)據(jù)都可以直接存入,包括 JavaScript 對(duì)象。對(duì)象倉(cāng)庫(kù)中,數(shù)據(jù)以 “鍵值對(duì)” 的形式保存,每一個(gè)數(shù)據(jù)記錄都有對(duì)應(yīng)的主鍵,主鍵是獨(dú)一無(wú)二的,不能有重復(fù),否則會(huì)拋出一個(gè)錯(cuò)誤;
  • 數(shù)據(jù)操作是異步的:使用 IndexedDB 執(zhí)行的操作是異步執(zhí)行的,以免阻塞應(yīng)用程序。
// 示例
var dbName = "my_db";

var request = indexedDB.open(dbName, 2);

request.onerror = function(event) {
  // 錯(cuò)誤處理
};

request.onupgradeneeded = function(event) {
  var db = event.target.result;

  // 建立一個(gè)對(duì)象倉(cāng)庫(kù)來(lái)存儲(chǔ)我們客戶的相關(guān)信息,我們選擇 ssn 作為鍵路徑(key path)
  // 因?yàn)?ssn 可以保證是不重復(fù)的
  var objectStore = db.createObjectStore("customers", { keyPath: "ssn" });

  // 建立一個(gè)索引來(lái)通過(guò)姓名來(lái)搜索客戶。名字可能會(huì)重復(fù),所以我們不能使用 unique 索引
  objectStore.createIndex("name", "name", { unique: false });

  // 使用郵箱建立索引,我們確保客戶的郵箱不會(huì)重復(fù),所以我們使用 unique 索引
  objectStore.createIndex("email", "email", { unique: true });

  // 使用事務(wù)的 oncomplete 事件確保在插入數(shù)據(jù)前對(duì)象倉(cāng)庫(kù)已經(jīng)創(chuàng)建完畢
  objectStore.transaction.oncomplete = function(event) {
    // 將數(shù)據(jù)保存到新創(chuàng)建的對(duì)象倉(cāng)庫(kù)
    var customerObjectStore = db.transaction("customers", "readwrite").objectStore("customers");
    customerData.forEach(function(customer) {
      customerObjectStore.add(customer);
    });
  };
};

Web SQL

Web SQL 數(shù)據(jù)庫(kù) API 實(shí)際上不是 HTML5 規(guī)范的一部分,而是一個(gè)單獨(dú)的規(guī)范,它引入了一組 API 來(lái)使用 SQL 來(lái)操作客戶端數(shù)據(jù)庫(kù)。需要注意的是,HTML5 已經(jīng)放棄 Web SQL 數(shù)據(jù)庫(kù)。

Web SQL Database 規(guī)范中定義的三個(gè)核心方法:

  1. openDatabase:這個(gè)方法使用現(xiàn)有數(shù)據(jù)庫(kù)或新建數(shù)據(jù)庫(kù)來(lái)創(chuàng)建數(shù)據(jù)庫(kù)對(duì)象;
  2. transaction:這個(gè)方法允許我們根據(jù)情況控制事務(wù)的提交或回滾;
  3. executeSql:這個(gè)方法用于執(zhí)行真實(shí)的 SQL 語(yǔ)句。

Web SQL 的特點(diǎn)(相比 Cookie、localStorage 與 sessionStorage):

  • Web SQL 能方便進(jìn)行對(duì)象存儲(chǔ);
  • Web SQL 支持事務(wù),能方便地進(jìn)行數(shù)據(jù)查詢和數(shù)據(jù)處理操作。
// 示例
var db = openDatabase('mydb', '1.0', 'Test DB', 2 * 1024 * 1024);

db.transaction(function (tx) { 
   // 執(zhí)行查詢操作
   tx.executeSql('CREATE TABLE IF NOT EXISTS LOGS (id unique, log)'); 
   // 執(zhí)行插入操作
   tx.executeSql('INSERT INTO LOGS (id, log) VALUES (1, "foobar")'); 
   tx.executeSql('INSERT INTO LOGS (id, log) VALUES (2, "logmsg")'); 
}); 
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容