前言
隨著Web應(yīng)用程序出現(xiàn)以來,人們對(duì)與能夠直接在客戶端上存儲(chǔ)信息能力的要求始終沒有停止過。應(yīng)用開發(fā)人員在找各種方式將數(shù)據(jù)存儲(chǔ)在客戶端上。從剛開始的Cookie存儲(chǔ)方案,到現(xiàn)在的Web Storage和indexedDB,本文將主要介紹這三種瀏覽器存儲(chǔ)方式優(yōu)缺點(diǎn)。
Cookie
1、Cookie是什么?
HTTP Cookie,通常直接叫做cookie,起初是在客戶端用于存儲(chǔ)會(huì)話信息的。該標(biāo)準(zhǔn)要求服務(wù)器對(duì) 任意 HTTP請(qǐng)求發(fā)送 Set-Cookie 而HTTP頭作為響應(yīng)的一部分,其中包含會(huì)話信息。例如,這種服務(wù)器響 應(yīng)的頭可能如下:
HTTP/1.1 200 OK
Content-type: text/html
Set-Cookie: name=value
Other-header: other-header-value
這個(gè)HTTP響應(yīng)設(shè)置以name為名稱、以value為值的一個(gè)cookie,名稱和值在傳送時(shí)都必須是 URL 編碼的。瀏覽器會(huì)存儲(chǔ)這樣的會(huì)話信息,并在這之后,通過為每個(gè)請(qǐng)求添加 Cookie ,HTTP 頭將信 息發(fā)送回服務(wù)器,如下所示:
GET /index.html HTTP/1.1
Cookie: name=value
Other-header: other-header-value
發(fā)送回服務(wù)器的額外信息可以用于唯一驗(yàn)證客戶來自于發(fā)送的哪個(gè)請(qǐng)求。
2、Cookie主要構(gòu)成:
-
name(名稱):一個(gè)唯一確定cookie的名稱。cookie的名稱必須是經(jīng)過URL編碼的。 -
value(值):儲(chǔ)存在cookie中的字符串值。值必須被URL編碼。 -
Domain(域):cookie對(duì)于哪個(gè)域是有效的。所有向該域發(fā)送的請(qǐng)求中都會(huì)包含這個(gè)cookie信息。 -
path(路徑):對(duì)于指定域中的那個(gè)路徑,應(yīng)該向服務(wù)器發(fā)送cookie。 -
Expires/Max-Age(失效時(shí)間):表示cookie何時(shí)應(yīng)該被刪除的時(shí)間戳(也就是,何時(shí)應(yīng)該停止向服務(wù)器發(fā)送這個(gè)cookie)。 -
HttpOnly:這個(gè)屬性是面試的時(shí)候??嫉?,如果這個(gè)屬性設(shè)置為true,就不能通過js腳本來獲取cookie的值,能有效的防止xss攻擊。 -
Secure(安全標(biāo)志):指定后,cookie只有在使用SSL連接的時(shí)候才發(fā)送到服務(wù)器。
3、Cookie的原理
第一次訪問網(wǎng)站的時(shí)候,瀏覽器發(fā)出請(qǐng)求,服務(wù)器響應(yīng)請(qǐng)求后,會(huì)在響應(yīng)頭里面添加一個(gè)
Set-Cookie,將cookie放入到響應(yīng)請(qǐng)求中,在瀏覽器第二次發(fā)請(qǐng)求的時(shí)候,會(huì)通過Cookie請(qǐng)求頭部將Cookie信息發(fā)送給服務(wù)器,服務(wù)端會(huì)辨別用戶身份,另外,Cookie的過期時(shí)間、域、路徑、有效期、適用站點(diǎn)都可以根據(jù)需要來指定。
4、Cookie生成方式
Cookie的生成方式主要有兩種:
- 服務(wù)端設(shè)置 cookie
客戶端第一次向服務(wù)端請(qǐng)求時(shí),在相應(yīng)的請(qǐng)求頭中就有set-cookie字段,用來標(biāo)識(shí)是哪個(gè)用戶。
下圖為登錄騰訊云服務(wù)端響應(yīng)頭截圖,cookie設(shè)置了相關(guān)的屬性:expires、path等。response headers服務(wù)端可以設(shè)置cookie 的所有選項(xiàng):expires、domain、path、secure、HttpOnly。
- 客戶端設(shè)置 cookie
cookie不像web Storage有setItem,getItem,removeItem,clear等方法,需要自己封裝。簡(jiǎn)單地在瀏覽器的控制臺(tái)里輸入:
document.cookie="name=lynnshen; age=18"
最簡(jiǎn)單的設(shè)置多個(gè)
cookie的方法就是重復(fù)執(zhí)行document.cookie = "key=name"
document.cookie = "name=lynnshen";
document.cookie = "age=18";
再看控制臺(tái):
5、Cookie設(shè)置、讀取、刪除方法的簡(jiǎn)單封裝
- 設(shè)置cookie
function setCookie(name, value, expires, path, domain, secure) {
var cookieText = encodeURIComponent(name) + "=" +
encodeURIComponent(value);
if (expires instanceof Date) {
cookieText += "; expires=" + expires.toGMTString();
}
if (path) {
cookieText += "; path=" + path;
}
if (domain) {
cookieText += "; domain=" + domain;
}
if (secure) {
cookieText += "; secure";
}
document.cookie = cookieText;
}
- 刪除cookie
function removeCookie(name, path, domain, secure){
this.set(name, "", new Date(0), path, domain, secure);
}
- 讀取cookie
function getCookie(name){
var cookieName = encodeURIComponent(name) + "=";
var cookieStart = document.cookie.indexOf(cookieName);
var cookieValue = null;
if (cookieStart > -1){
var cookieEnd = document.cookie.indexOf(";", cookieStart);
if (cookieEnd == -1){
cookieEnd = document.cookie.length;
}
cookieValue = decodeURIComponent(document.cookie.substring(
cookieStart + cookieName.length, cookieEnd));
}
return cookieValue;
}
6、Cookie的缺點(diǎn)
-
每個(gè)特定域名下的cookie數(shù)量有限:
IE6或IE6-(IE6以下版本):最多20個(gè)cookie
IE7或IE7+(IE7以上版本):最多50個(gè)cookie
FF:最多50個(gè)cookie
Opera:最多30個(gè)cookie
Chrome和safari沒有硬性限制
當(dāng)超過單個(gè)域名限制之后,再設(shè)置cookie,瀏覽器就會(huì)清除以前設(shè)置的cookie。IE和Opera會(huì)清理近期最少使用的cookie,FF會(huì)隨機(jī)清理cookie。
存儲(chǔ)量太小,只有
4KB。每次
HTTP請(qǐng)求都會(huì)發(fā)送到服務(wù)端,影響獲取資源的效率。需要自己封裝獲取、設(shè)置、刪除
cookie的方法。
Web Storage
最初的Web Storage 規(guī)范包含了兩種對(duì)象的定義:sessionStorage和globalStorage。這兩個(gè)對(duì)象在支持的瀏覽器中都是以windows對(duì)象屬性的形式存在的。而localStorage對(duì)象在修訂過的HTML 5規(guī)范中作為持久保存客戶端數(shù)據(jù)的方案取代了
globalStorage。所以現(xiàn)在主要談?wù)摰氖?code>sessionStorage和localStorage兩種。
1、web Storage的主要作用:
- 提供一種在
cookie之外存儲(chǔ)會(huì)話數(shù)據(jù)的途徑; - 提供一種存儲(chǔ)大量可以跨會(huì)話存在的數(shù)據(jù)的機(jī)制。
2、web Storage 的主要方法:
-
clear(): 刪除所有值;Firefox中沒有實(shí)現(xiàn) 。 -
getItem(name):根據(jù)指定的名字name獲取對(duì)應(yīng)的值。 -
key(index):獲得index位置處的值的名字。 -
removeItem(name):刪除由name指定的名值對(duì)兒。
注意: Storage 類型只能存儲(chǔ)字符串。非字符串的數(shù)據(jù)在存儲(chǔ)之前會(huì)被轉(zhuǎn)換成字符串。
localStorage
1、localStorage的特點(diǎn)
- 保存的數(shù)據(jù)長(zhǎng)期存在,下一次訪問該網(wǎng)站的時(shí)候,網(wǎng)頁(yè)可以直接讀取以前保存的數(shù)據(jù)。
- 大小為5M左右
- 僅在客戶端使用,不和服務(wù)端進(jìn)行通信
- 接口封裝較好
基于上面的特點(diǎn),LocalStorage可以作為瀏覽器本地緩存方案,用來提升網(wǎng)頁(yè)首屏渲染速度(根據(jù)第一請(qǐng)求返回時(shí),將一些不變信息直接存儲(chǔ)在本地)。
2、localStorage的使用
//使用方法存儲(chǔ)數(shù)據(jù)
localStorage.setItem("name", "Nicholas");
//使用屬性存儲(chǔ)數(shù)據(jù)
localStorage.book = "Professional JavaScript";
//使用方法讀取數(shù)據(jù)
var name = localStorage.getItem("name");
//使用屬性讀取數(shù)據(jù)
var book = localStorage.book;
數(shù)據(jù)的保留是通過 JavaScript 刪除或者是用戶清除瀏覽器緩存。
sessionStorage
1、什么是 sessionStorage ?
-
sessionStorage對(duì)象存儲(chǔ)特定于某個(gè)會(huì)話的數(shù)據(jù),也就是該數(shù)據(jù)只保持到瀏覽器關(guān)閉。 -
sessionStorage就像會(huì)話cookie,也會(huì)在瀏覽器關(guān)閉后消失。 - 存儲(chǔ)在
sessionStorage中的數(shù)據(jù)可以跨越頁(yè)面刷新而存在,同時(shí)如果瀏覽器支持,瀏覽器崩潰并重啟之后依然可用(Firefox 和 WebKit都支持,IE則不行)。 -
seesionStorage對(duì)象綁定于某個(gè)服務(wù)器會(huì)話,所以當(dāng)文件在本地運(yùn)行的時(shí)候是不可用的。 - 存儲(chǔ)在
sessionStorage中的數(shù)據(jù)只能由最初給對(duì)象存儲(chǔ)數(shù)據(jù)的頁(yè)面訪問到,所以對(duì)多頁(yè)面應(yīng)用有限制。
2、sessionStorage的特點(diǎn):
- 會(huì)話級(jí)別的瀏覽器存儲(chǔ)
- 大小為5M左右
- 僅在客戶端使用,不和服務(wù)端進(jìn)行通信
- 接口封裝較好
基于上面的特點(diǎn),sessionStorage可以有效對(duì)表單信息進(jìn)行維護(hù),比如刷新時(shí),表單信息不丟失。
3、localStorage 的使用
//使用方法存儲(chǔ)數(shù)據(jù)
sessionStorage.setItem("name", "Nicholas");
//使用屬性存儲(chǔ)數(shù)據(jù)
sessionStorage.book = "Professional JavaScript";
//使用方法讀取數(shù)據(jù)
var name = sessionStorage.getItem("name");
//使用屬性讀取數(shù)據(jù)
var book = sessionStorage.book;
sessionStorage 對(duì)象應(yīng)該主要用于僅針對(duì)會(huì)話的小段數(shù)據(jù)的存儲(chǔ)。如果需要跨越會(huì)話存儲(chǔ)數(shù)據(jù), 那么localStorage更為合適。
IndexedDB
1、IndexedDB 是什么?
Indexed Database API,或者簡(jiǎn)稱為IndexedDB,是在瀏覽器中保存結(jié)構(gòu)化數(shù)據(jù)的一種數(shù)據(jù)庫(kù)。IndexedDB 的思想是創(chuàng)建一套 API,方便保存和讀取 JavaScript 對(duì)象,同時(shí)還支持查詢及搜索。
2、IndexedDB 的特點(diǎn)
-
鍵值對(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ú)一無二的,不能有重復(fù),否則會(huì)拋出一個(gè)錯(cuò)誤。 -
異步:IndexedDB操作時(shí)不會(huì)鎖死瀏覽器,用戶依然可以進(jìn)行其他操作,這與LocalStorage形成對(duì)比,后者的操作是同步的。異步設(shè)計(jì)是為了防止大量數(shù)據(jù)的讀寫,拖慢網(wǎng)頁(yè)的表現(xiàn)。 -
支持事務(wù):IndexedDB支持事務(wù)(transaction),這意味著一系列操作步驟之中,只要有一步失敗,整個(gè)事務(wù)就都取消,數(shù)據(jù)庫(kù)回滾到事務(wù)發(fā)生之前的狀態(tài),不存在只改寫一部分?jǐn)?shù)據(jù)的情況。 -
同源限制:IndexedDB受到同源限制,每一個(gè)數(shù)據(jù)庫(kù)對(duì)應(yīng)創(chuàng)建它的域名。網(wǎng)頁(yè)只能訪問自身域名下的數(shù)據(jù)庫(kù),而不能訪問跨域的數(shù)據(jù)庫(kù)。 -
儲(chǔ)存空間大:IndexedDB的儲(chǔ)存空間比localStorage大得多,一般來說不少于 250MB,甚至沒有上限。
-支持二進(jìn)制儲(chǔ)存:IndexedDB不僅可以儲(chǔ)存字符串,還可以儲(chǔ)存二進(jìn)制數(shù)據(jù)(ArrayBuffer 對(duì)象和 Blob 對(duì)象)。
3、IndexedDB 基本指令
- 建立打開IndexedDB :
window.indexedDB.open("testDB") - 關(guān)閉IndexedDB:
indexdb.close() - 刪除IndexedDB:
window.indexedDB.deleteDatabase(indexdb)
4、webStorage、cookie 和 IndexedDB之間的區(qū)別
從上圖可以看到,
cookie已經(jīng)不建議用于存儲(chǔ)。如果沒有大量數(shù)據(jù)存儲(chǔ)需求的話,可以使用 localStorage 和 sessionStorage 。對(duì)于不怎么改變的數(shù)據(jù)盡量使用 localStorage 存儲(chǔ),否則可以用 sessionStorage 存儲(chǔ)。
總結(jié)
web存儲(chǔ)可以說是必須要重點(diǎn)理解和掌握的知識(shí)點(diǎn)了,特別是web Storage經(jīng)常會(huì)使用到。最后總結(jié)用一句話總結(jié)三種存儲(chǔ)方案。
- Cookie 的本職工作并非本地存儲(chǔ),而是“維持狀態(tài)”。
- Web Storage 是 HTML5專門為瀏覽器存儲(chǔ)而提供的數(shù)據(jù)存儲(chǔ)機(jī)制,不與服務(wù)端發(fā)生通信。
- IndexedDB 用于客戶端存儲(chǔ)大量結(jié)構(gòu)化數(shù)據(jù)。