這一次帶你徹底瞭解前端本地存儲

隨着Web應用程序的出現,直接在客戶端存儲用戶信息的需求也隨之出現。那麼我們前端常用的存儲方式有哪些呢?

前言

如果這篇文章有幫助到你,❤️關注+點贊❤️鼓勵一下作者,文章公衆號首發,關注 前端南玖 第一時間獲取最新的文章~

HTML5常用的幾種存儲方式

  • 本地存儲:localStorage, sessionStorage, cookies
  • 離線緩存:application cache
  • 前端數據庫:indexedDB, webSQL

HTTP cookie 通常也叫做cookie,最初用於在客戶端存儲會話信息。cookie是與特定域名綁定的,設置cookie後,它會與請求一起發送到創建它的域。 這個限制能保證cookie中存儲的信息只對被認可的接收者開放,不被其它域訪問。

cookie的構成

  • 名稱: 唯一標識cookie的名稱。cookie不區分大小寫,cookie名必須經過URL編碼。
  • 值: 存儲在cookie裏的字符串值,這個值必須經過URL編碼。
  • 域: cookie的有效域,發送到這個域的所有請求都會包含對應的cookie。
  • 路徑: 請求URL中包含這個路徑纔會把cookie發送到服務器。
  • 過期時間: 表示何時刪除cookie的時間戳。(即什麼時間之後就不會發送到服務器了)
  • 安全標識: 設置之後,只在使用SSL安全連接的情況下才會把cookie發送到服務器。

限制

因爲cookie存儲在客戶端機器上,所以爲保證它不會被惡意利用,瀏覽器會施加限制。

  • 不超過300個cookie
  • 每個cookie不超過4096字節(4kb)
  • 每個域不超過20個cookie
  • 每個域不超過81920字節

JavaScript中的cookie

在JavaScript中處理cookie比較麻煩,因爲接口過於簡單,只有BOMdocument.cookie屬性。

獲取cookie

document.cookie返回包含頁面中所有有效cookie的字符串,以分號分隔;

name1=value1;name2=valve2;name3=value3

所有名和值都是URL編碼,因此必須使用decodeURIComponent()解碼

設置cookie

name=value; expires=expiration_time; path=domain_path; domain=domain_namel secure
//在所有這些參數中,只有cookie的名稱和值是必須的

document.cookie = `${encodeURIComponent('name')}=${encodeURIComponent('nanjiu')};domain=bettersong.github.io;`

刪除cookie

沒有直接刪除已有cookie的方法,但可以通過設置其過期時間來達到刪除效果;

document.cookie = 'uid=dkfywqkrhkwehf23;expires=' + new Date(0) + ';path=/;secure;

cookie是如何工作的?

request:

當瀏覽器發起一個請求時,瀏覽器會自動檢查是否有相應的cookie,如果有則將cookie添加到Request HeadersCookie字段中

response:

當服務器需要cookie時,在http請求的Response Headers字段中添加Set-Cookie字段,瀏覽器接收到之後會自動解析識別,將cookie種下。

localStorage 和sessionStorage

localStorage只要在相同的協議,域名,端口下就能讀取或修改同一份localStorage數據,sessionStorage對象只存儲會話數據,這意味着數據只會存儲到瀏覽器關閉。sessionStorage除了協議,域名,端口外,還要求在同一窗口下。

  • localStorage 永久存儲,除非手動刪除。
  • sessionStorage存儲到瀏覽期關閉就消失了
  • 每個域名給localStorage和sessionStorage分配的存儲空間時5M ,cookie是4kb

方法

setItem('key','value')  // 存儲數據

getItem('key')	// 讀取數據

remove('key')	// 刪除數據

clear()	// 清空

**⚠️注意:Storage類型智能存儲字符串。非字符串數據在存儲之前會自動轉換爲字符串,並且這種轉換不能在獲取數據時撤銷,也就是說你在獲取storage數據時,拿到的一定是字符串,需要自己手動轉 **

存儲JSON對象的數據

Storage是以字符串保存數據的,所以在保存JSON格式的數據之前,最好把數據轉化爲字符串,這個操作叫序列化

let obj = {
  name: '南玖',
  age: 18
}
localStorage.setItem('author',JSON.stringify(obj))

const author = JSON.parse(localStorage.getItem('author'))

localStorage與sessionStorage的異同

相同點: 兩者的API完全相同,都是在瀏覽器端存儲數據,存儲大小都是5M

不同點:

  1. localStorage存儲的數據是永久性數據,頁面刷新,即使瀏覽器重啓,甚至操作系統重啓也不會丟失,並且存儲的數據在同源(協議、域名、端口號一致)下的標籤頁和window窗口之間共享。
  2. sessionStorage存儲的數據有些苛刻,頁面刷新仍然有效,選項卡關閉時數據丟失。但是在相同標籤頁打開的多個iframe之間數據可以共享(同源的情況下)。

存儲事件

每當Storage對象發生變化時,都會觸發storage事件。(增刪改查)

這個事件的時間對象有4個屬性:

  • domain:存儲變化對應的域
  • key:被設置或被刪除的鍵
  • newValue:鍵被設置的新值,若被刪除則爲null
  • oldValue:鍵變化之前的值
window.addEventListener('storage', e=>{
    console.log(e.domain)
})

對於sessionStoragelocalStorage上的任何更改都會觸發storage事件,但storage事件不會區分這兩者

IndexedDB

Indexed Database API簡稱 IndexedDB,是瀏覽器中存儲結構話數據的一個方案。IndexedDB用於代替目前已廢棄的 Web SQL

基本概念

  • Database:通過open方法直接打開
const db = indexDB.open('testDB');
  • Object store:這個就是DB裏面具體存儲的對象。這個可對應SQL裏面的table內容。其存儲的結構爲:

  • Index:有點類似於外鏈,它本身是一種Object store,主要用來本體的store中,索引另外的object store裏面的數據。
// 創建 index
var myIndex = objectStore.index('lName'); 
  • transaction: 事務其實就是一系列 CRUD 的集合內容。如果其中一個環節失敗了,那麼整個事務的處理都會被取消。
  • cursor: 主要是用來遍歷 DB 裏面的數據內容。主要是通過 openCursor 來進行控制。

創建數據庫

const request = indexedDB.open(dbName);

request.onerror = function(event) {
  // 錯誤處理程序。
};
request.onupgradeneeded = function(event) {
  var db = event.target.result;
  // 設置 id 爲 primaryKey 參數
  var objectStore = db.createObjectStore("customers", { keyPath: "id",{autoIncrement:true} });
  
  // 設置指定索引,並確保唯一性
  objectStore.createIndex("name", "name", { unique: false });
  objectStore.createIndex("email", "email", { unique: true });

};

創建 Object Store

使用的方法就是 IDBDatabase 上的 createObjectStore 方法。

const objectStore = db.createObjectStore("customers", { keyPath: "id",{autoIncrement:true} });
  • keyPath: 用來設置主鍵的 key,具體區別可以參考下面的 keyPath 和 generator 的區別。
  • autoIncrement: 是否使用自增 key 的特性。

創建的 key 主要是爲了保證,在數據插入時唯一性的標識。

設置索引 index

在完成 PK(Primary key) 創建完畢後,爲了更好的搜索性能我們還需要額外創建 index。這裏可以直接使用:

objectStore.createIndex('indexName', 'property', options);
  • indexName: 設置當前 index 的名字
  • property: 從存儲數據中,指明 index 所指的屬性。

其中,options 有三個選項:

  • unique: 當前 key 是否能重複 (最常用)
  • multiEntry: 設置當前的 property 爲數組時,會給數組裏面每個元素都設置一個 index 值。
// 創建一個名字叫 titleIndex 的 index,並且存儲的 index 不能重複
DB.createIndex('titleIndex', 'title', {unique: false});

增刪數據

在 IndexedDB 裏面進行數據的增刪,都需要在 transaction 中完成。而這個增刪數據,大家可以理解爲一次 request,相當於在一個 transaction 裏面管理所有當前邏輯操作的 request。所以,在正式開始進行數據操作之前,還需要給大家簡單介紹一些如果創建一個事務。

事務的創建

transaction API,在創建時,你需要手動指定當前 transaction 是那種類型的操作,基本的內容有:

  • "readonly":只讀
  • "readwrite":讀寫
  • "versionchange":這個不能手動指定,會在 upgradeneeded 回調事件裏面自動創建。它可以用來修改現有 object store 的結構數據,比如 index 等。

你可以通過在數據庫打開之後,通過 IDBDataBase 上的 transaction 方法創建

const transaction = db.transaction(["customers"], "readwrite");
const objectStore = transaction.objectStore("customers");
 // 遍歷存儲數據
for (let i in customerData) {
  const request = objectStore.add(customerData[i]);
  request.onsuccess = function(event) {
    // success, done?
  };
}

操作數據

完成了事務的創建之後,我們就可以正式的開始進行數據的交互操作了,也就是寫我們具體的業務邏輯。如下,一個完整數據事務的操作。

const tx = db.transaction("books", "readwrite");
const store = tx.objectStore("books");

store.put({title: "aaaaa", author: "Fred", isbn: 1111});
store.put({title: "bbbbb", author: "Fred", isbn: 2222});
store.put({title: "ccccc", author: "Barney", isbn: 3333});

tx.oncomplete = function() {
  // All requests have succeeded and the transaction has committed.
};

索引數據

索引數據是所有數據庫裏面最重要的一個。這裏,我們可以使用index 來做。例如,通過 index 來快速索引 key 值

const index = objectStore.index("username");
index.openCursor.onsuccess = function(event) {
  // 處理成功
};

點贊、收藏和評論

我是前端南玖,感謝各位的:點贊、收藏和評論,我們下期見!

加入前端交流羣928029210,我們一起學習~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章