Web Storage規(guī)范
是HTML5的一部分
目的:克服由cookie帶來的一些限制,當(dāng)數(shù)據(jù)需要被嚴(yán)格的控制在客戶端時(shí),無須持續(xù)的將數(shù)據(jù)發(fā)回服務(wù)器。
目標(biāo):
- 提供一種cookie之外的存儲會話數(shù)據(jù)的途徑
- 提供一種存儲大量可以跨session存在的數(shù)據(jù)的機(jī)制
定義:
Web Storage規(guī)范包含兩種對象的定義:sessionStorage和globalStorage**。這兩個(gè)對象在支持的瀏覽器中都是以 window 對象屬性
的形式存在的。
注意:在使用之前記得查看其瀏覽器支持情況
Storage類型
Storage類型的方法:
- clear(): 刪除所有值
- getItem(name): 根據(jù)指定的名字 name 獲取對應(yīng)的值
- setItem(name, value): 為指定的name設(shè)置一個(gè)對應(yīng)的值
- key(index):獲得index位置處的值的名字。
-
removeItem(name):刪除name指定的鍵值對。
還可以通過length屬性來判斷有多少鍵值對存放在Storage對象中
注意: Storage類型只能存儲字符串。非字符串的數(shù)據(jù)在存儲之前會被轉(zhuǎn)換為字符串
sessionStorage對象
sessionStorage 對象是存儲特定于某個(gè)會話的數(shù)據(jù),當(dāng)頁面被重新加載時(shí)其仍然存在,只有當(dāng)瀏覽器被關(guān)閉或者當(dāng)前頁面被關(guān)閉時(shí),數(shù)據(jù)才會被清除;可以理解為數(shù)據(jù)被存儲在瀏覽器中,只有瀏覽器被關(guān)閉后,數(shù)據(jù)才會被清除,同時(shí),如果瀏覽器支持,在瀏覽器崩潰并重啟之后仍然可以訪問存儲與sessionStorage中的數(shù)據(jù)
因?yàn)閟essionStorage對象綁定于某個(gè)服務(wù)器會話,所以當(dāng)文件在本地運(yùn)行的時(shí)候是不可用的。
存儲在sessionStorage中的數(shù)據(jù)只能由最初給對象存儲數(shù)據(jù)的頁面訪問到,其只針對于當(dāng)前會話,所以對多頁面應(yīng)用有限制。
使用
sessionStorage對象是Storage的一個(gè)實(shí)例,所以可以使用setItem()或者直接設(shè)置新的屬性存儲數(shù)據(jù)
如:
// 使用方法存儲數(shù)據(jù)
sessionStorage.setItem('name', 'Hexon');
// 使用屬性存儲數(shù)據(jù)
sessionStorage.book = 'Professional Javascript';
// 使用方法讀取數(shù)據(jù)
var name = sessionStorage.getItem('name');
// 使用方法讀取數(shù)據(jù)
var book = sessionStorage.book;
// 通過key來迭代存儲與sessionStorage中的鍵值
for (var i = 0, len = sessionStorage.length; i < len; i++) {
var key = sessionStorage.key(i);
var value = sessionStorage.getItem(key);
alert(key + '=' + value);
}
// 使用for-in循環(huán)迭代sessionStorage中的值
for (var key in sessionStorage) {
val value = sessionstorage.getItem(key);
alert(key + '=' + value);
不同的瀏覽器寫入數(shù)據(jù)方面略有不同,F(xiàn)ireFox和WebKit實(shí)現(xiàn)了同步寫入,所以添加到存儲空間中的數(shù)據(jù)是立刻被提交的。而IE的實(shí)現(xiàn)是異步寫入數(shù)據(jù),在設(shè)置數(shù)據(jù)和將數(shù)據(jù)寫入磁盤之間可能有延遲
總結(jié):sessionStorage對象應(yīng)該只用于針對會話的小段數(shù)據(jù)存儲。如果需要跨會話存儲數(shù)據(jù),那么localStorage或者globalStorage更合適
globalStorage對象
只用FireFox2中實(shí)現(xiàn)了globalStorage對象,主要目的是為了實(shí)現(xiàn) 跨會話存儲數(shù)據(jù),但有特定的訪問限制。
要使用globalStorage,首先要指定哪些域名可以訪問該數(shù)據(jù)。
使用方法:
// 只針對 域名 wrox.com 的存儲訪問
globalStorage['wrox.com'].name = 'hexon';
var name = globaleStorage['wrox.com'].name;
注意:
- globalStorage對象不是Storage的實(shí)例,而具體的globalStorage['wrox.com'] 才是
- 當(dāng)使用
globalStorage[''].name = 'hexon'
來存儲數(shù)據(jù)時(shí),表示任何人都可以訪問,一定不要這樣做,不安全 - 對globalStorage空間的訪問,是依據(jù)發(fā)起請求的頁面的域名、協(xié)議和端口 來限制的;如使用https協(xié)議在wrox.com中存儲了數(shù)據(jù),那么通過http訪問的wrox.com的頁面將無法訪問該數(shù)據(jù)
- 如果事先無法確定域名,那么使用 location.host 作為屬性名比較安全,表示頁面必須來自于同一個(gè)域名、協(xié)議和端口,才可以訪問
- 如果不使用removeItem() 或者 delete 刪除,或者用戶未清除瀏覽器緩存,存儲在globalStorage屬性中的數(shù)據(jù)將會一直保存在磁盤上
注意: globalStorage對象在修訂過的HTML5規(guī)范中被localStorage對象所取代
localStorage 對象
localStorage對象在修訂過的HTML5規(guī)范中作為持久保存客戶端數(shù)據(jù)的方案取代了globalStorage。
與globalStorage不同,不能給localStorage指定規(guī)則,規(guī)則在HTML5規(guī)范中就被制定,要訪問同一個(gè)localStorage對象,頁面必須來自同一個(gè)域名(子域名無效)、同一種協(xié)議,在同一端口上,這相當(dāng)于 globalStorage[location.host]
;
localStorage是Storage類型的實(shí)例,因此可以像使用sessionStorage一樣使用它
同時(shí), 為了兼容只支持globalStorage對象的瀏覽器,可以使用以下方式進(jìn)行能力檢測:
function getLocalStorage() {
if (tpyeof localStorage === 'object') {
return localStorage;
} else if (typeof globalStorage === 'object') {
return globalStorage[location.host];
} else {
throw new Error('Local Storage not available.');
}
}
sessionStorage和localStorage的對比與使用
概念
這兩者都是本地存儲,均不會被發(fā)送到服務(wù)器端,其主要在生命周期上有比較明顯的區(qū)別;localStorage的生命周期更長,沒有過期時(shí)間,原則上要等到通過JavaScript將內(nèi)容清除掉或者清空cookie時(shí)才會消失;而sessionStorage則在Browser或Tab被關(guān)閉時(shí)就會清空
限制
- 對于localStorage而言,大多數(shù)桌面瀏覽器會設(shè)置每個(gè)來源5MB的限制,具體依瀏覽器而異
- 對于sessionStorage,也因?yàn)g覽器而異,一般每個(gè)來源在2.5MB ~ 5MB 之間
瀏覽器支持情況
這兩者都都需要瀏覽器的API支持,瀏覽器的支持情況如下:
使用
通過window.localStorage
和window.sessionStorage
這而兩個(gè)對象進(jìn)行操作
以操作localStorage
為例:
-
從存儲中獲取值
window.localStorage.getItem('key')
function setStyles() {
var currentColor = localStorage.getItem('bgcolor');
var currentFont = localStorage.getItem('font');
var currentImage = localStorage.getItem('image');
document.getElementById('bgcolor').value = currentColor;
document.getElementById('font').value = currentFont;
document.getElementById('image').value = currentImage;
htmlElem.style.backgroundColor = '#' + currentColor;
pElem.style.fontFamily = currentFont;
imgElem.setAttribute('src', currentImage);
}
-
在存儲中設(shè)置值
window.localStorage.setItem
可以從存儲中獲取指定的數(shù)據(jù)項(xiàng)或者設(shè)置新的數(shù)據(jù)項(xiàng),該方法接受兩個(gè)參數(shù)——要?jiǎng)?chuàng)建/修改的數(shù)據(jù)項(xiàng)的鍵,和對應(yīng)的值。
function populateStorage() {
localStorage.setItem('bgcolor', document.getElementById('bgcolor').value);
localStorage.setItem('font', document.getElementById('font').value);
localStorage.setItem('image', document.getElementById('image').value);
setStyles();
}
-
通過 StorageEvent 響應(yīng)存儲的變化
無論何時(shí),storage對象發(fā)生變化時(shí)(即創(chuàng)建/更新/刪除,重復(fù)設(shè)置相同的項(xiàng)不會觸發(fā),storage.clear()方法至多觸發(fā)一次),都會觸發(fā)StorageEvent事件
window.addEventListener('storage', function(){});
示例:
window.addEventListener('storage', function(e) {
document.querySelector('.my-key').textContent = e.key;
document.querySelector('.my-old').textContent = e.oldValue;
document.querySelector('.my-new').textContent = e.newValue;
document.querySelector('.my-url').textContent = e.url;
document.querySelector('.my-storage').textContent = e.storageArea;
});
注意:在同一個(gè)頁面內(nèi)發(fā)生的改變不會起作用——在相同域名下的其他頁面(如一個(gè)新標(biāo)簽或 iframe)發(fā)生的改變才會起作用。在其他域名下的頁面不能訪問相同的 Storage 對象。
-
刪除數(shù)據(jù)記錄
window.localStorage.removeItem()
:接收一個(gè)參數(shù),要?jiǎng)h除的數(shù)據(jù)項(xiàng)key值
window.localStorage.clear()
:不接收參數(shù),只是簡單的清空域名對應(yīng)的整個(gè)存儲數(shù)據(jù)
cookie
起源: 最初由網(wǎng)景公司引入,用于在客戶端存儲回話信息
工作方式:要求服務(wù)器對任意HTTP請求,在響應(yīng)頭中添加Set-Cookie 字段來設(shè)置cookie,在客戶端接收到這個(gè)cookie信息之后,將其存儲起來,在此之后,當(dāng)客戶端再給創(chuàng)建它的域名發(fā)送HTTP請求時(shí),都會在HTTP頭中添加cookie信息,服務(wù)器可以根據(jù)這個(gè)cookie信息來決定該用戶可以執(zhí)行哪些操作(例如:是否允許它進(jìn)行訪問)
,
cookie的組成:
cookie由瀏覽器保存在客戶端計(jì)算機(jī)中,由以下幾塊信息組成:
- 名稱:cookie的名稱,這是唯一的,且字符不區(qū)分大小寫。注意:cookie的名稱必須是經(jīng)過URL編碼的
- 值:存儲在cookie中的字符串值。注意:值必須經(jīng)過URL編碼
- 域:cookie對于哪個(gè)域有效,所有向該域發(fā)送的請求中,都會包含這個(gè)cookie信息,如果沒有設(shè)置,則這個(gè)域會被認(rèn)作是設(shè)置cookie的那個(gè)域
- 路徑:對于域下的路徑訪問,會包含cookie信息
- 失效時(shí)間
- 安全標(biāo)志
一個(gè)服務(wù)器發(fā)給客戶端的SetCookie信息,如下:
HTTP/1.1 200 OK
Content-type: text/html
Set-cookie: name=value; expires=Mon, 22-Jan-07 07:10:24 GMT; domain=.wrox.com; path=/; secure
Other-header: other-header-value
Set-cookie: name=value; expires=Mon, 22-Jan-07 07:10:24 GMT domain=.wrox.com; path=/; secure
這個(gè)Set-cookie的解釋如下:
- cookie名稱: name
- cookie的值:value (注意:值跟名稱是不同的東西)
- 失效時(shí)間:Mon, 22-Jan-07 07:10:24 GMT;(這是GMT時(shí)間)
- 域名: .wrox.com
- 路徑: /
- 安全標(biāo)志: secure(只有當(dāng)客戶端通過SSH連接時(shí),才可以傳輸該cookie)
cookie的特點(diǎn):
- 創(chuàng)建方式:是由服務(wù)器來創(chuàng)建 cookie 信息的
- 存放位置:客戶端接收到服務(wù)器的cookie信息之后,將其存放在客戶端的計(jì)算機(jī)中
- cookie個(gè)數(shù)限制:cookie是綁定在域名下的,因此每個(gè)域的cookie個(gè)數(shù)是有限的,不同瀏覽器的限制不同,一般為50個(gè),chrome和safari沒有硬性限制。
- cookie尺寸限制:對于每個(gè)域下的cookie的尺寸限制為4K字節(jié),注意:是一個(gè)域下的所有cookie的總尺寸之和要小于4K字節(jié),不是單個(gè)cookie的尺寸
- 失效時(shí)間:默認(rèn)情況下,瀏覽器會話結(jié)束時(shí)即將所有的cookie刪除,但是,可以自己設(shè)置失效時(shí)間,當(dāng)未到達(dá)失效時(shí)間時(shí),cookie將一直保存在客戶端計(jì)算機(jī)中,除非自己手動刪除
- cookie會被附加在每個(gè)http請求中,因此會增加流量
- 安全標(biāo)志:當(dāng)指定后(通過Set-Cookie中添加 secure 關(guān)鍵字即可),cookie只有在使用SSL連接的時(shí)候才發(fā)送到服務(wù)器
注意事項(xiàng):
- cookie個(gè)數(shù)和尺寸的限制,超過限制后,不同的瀏覽器有不同的處理方式,因此,一定不要超過限制
- 域、路徑、失效時(shí)間和secure標(biāo)志都是服務(wù)器給瀏覽器的指示,以指定何時(shí)應(yīng)該發(fā)送cookie,這些參數(shù)不會作為發(fā)送給服務(wù)器cookie信息的一部分
- cookie的名稱是經(jīng)過URL編碼的,注意:是名稱
- Javascipt中處理cookie有些復(fù)雜,主要是接口不好用,即:document.cookie
cookie的缺陷
- cookie會被附加在每個(gè)http請求中,因此會無形中增加流量
- 由于http請求中的cookie是明文傳輸,因此有安全問題(除非使用https),不要使用cookie存放重要的數(shù)據(jù)
- cookie的大小限制是4kb,對于復(fù)雜的存儲需求可能不夠用
cookie的使用
- 獲取cookie:
document.cookie
,通過該方法可以獲取cookie - 刪除cookie:設(shè)置
document.cookie
并不會覆蓋cookie,除非設(shè)置的cookie的名稱已經(jīng)存在。那么就會對原cookie進(jìn)行覆蓋
封裝的cookie代碼:
let CookieUtil = {
get: (name) => {
let cookieName = encodeURIComponent(name) + "=",
cookieStart = document.cookie.indexOf(cookieName),
cookieValue = null;
if (cookieStart > -1) {
let cookieEnd = document.cookie.indexOf(';', cookieStart);
if (cookieEnd === -1) {
cookieEnd = document.cookie.length;
}
cookieValue = decodeURIComponent(document.cookie.substring(cookieStart + cookieName.length, cookieEnd));
}
return cookieValue;
},
set: function (name, value, expires, path, domain, secure) {
let 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, 并沒有直接的刪除cookie的方法,這里通過重新設(shè)置cookie名稱,來對cookie進(jìn)行替換
// 同時(shí) 將過期時(shí)間expires設(shè)置為過去的時(shí)間,
unset: function(name, path, domain, secure) {
this.set(name, '', new Date(0), path, domain, secure);
}
}
瀏覽器本地存儲中 cookie 和 localStorage 有什么區(qū)別? localStorage 如何存儲刪除數(shù)據(jù)。
sessionStorage、localStorage和cookie 這三者都是用于瀏覽器端存儲數(shù)據(jù),而且都是字符串類型的鍵值對。
區(qū)別在于:
- 數(shù)據(jù)傳輸方面:在每個(gè)http請求中都會附加cookie信息,cookie中的信息能夠被推送到服務(wù)器端;而sessionStorage和localStorage不會被推送到服務(wù)器端
- 存儲大小不同:cookie最大支持4KB,而sessionStorage和localStorage一般在2.5~10MB
- 生命周期:默認(rèn)情況下,cookie開始于瀏覽器啟動,結(jié)束于瀏覽器關(guān)閉,但是可以手動設(shè)置cookie的過期時(shí)間,同時(shí),到期后被刪除;而對于localStorage,沒有過期時(shí)間,原則上只要不手動刪除,其會一直被保存在本地上,sessionStorage的數(shù)據(jù)關(guān)閉瀏覽器時(shí)清除
-
被創(chuàng)造的初衷不同:sessionStorage和localStorage都屬于WebStorage,創(chuàng)建他們的目的就是用于存儲客戶端數(shù)據(jù);
而cookie最早在網(wǎng)景的瀏覽器中被支持,主要目的是為了辨別用戶身份而存儲在本地終端的數(shù)據(jù)。
參考:在HTML5的時(shí)代,重新認(rèn)識Cookie
參考:
- 使用 Web Storage API
- [HTML5]簡述HTML5的Client端暫存-localStorage/sessionStorage
- Storing Objects in HTML5 localStorage
- HTML5本地存儲:SessionStorage, LocalStorage, Cookie
- What is the difference between localStorage, sessionStorage, session and cookies?