HTML5在客戶端存儲(chǔ)上推出的兩種新方法。之前都是由cookie完成, 但是cookie并不適合做大量數(shù)據(jù)的存儲(chǔ),嚴(yán)重影響數(shù)據(jù)傳輸效率。但cookie能實(shí)現(xiàn)跨域(在請(qǐng)求上由請(qǐng)求決定),而他們不能,這里先不談這點(diǎn)。

* Web存儲(chǔ)有兩種方式: localStorage 和 sessionStorage
localStorage定義
?網(wǎng)上常解釋:localStorage 用于持久化的本地存儲(chǔ),除非主動(dòng)刪除數(shù)據(jù),否則數(shù)據(jù)是永遠(yuǎn)不會(huì)過(guò)期。總感覺(jué)還沒(méi)明白,我理解是:localStorage 是一種持久化的存儲(chǔ),它能將數(shù)據(jù)存儲(chǔ)到本地硬盤當(dāng)中,因此數(shù)據(jù)沒(méi)有時(shí)間限制,不會(huì)因?yàn)橐淮螘?huì)話結(jié)束或關(guān)機(jī)等操作而消失,除非我們主動(dòng)清除。
localStorage 的使用
localStorage 用 setItem()方法來(lái)設(shè)置值,用 getItem() 方法獲取值。
html代碼
<div id="result"></div>
javascript代碼
// 檢查瀏覽器支持性
if ( typeof(Storage) && typeof(localStorage) ) {
// 添加值
localStorage.setItem("sayHi", "Hello World!");
// 取值
document.getElementById("result").innerHTML = localStorage.getItem("sayHi");
} else {
document.getElementById("result").innerHTML = "您的瀏覽器不支持 Web Storage ...";
}
效果展示

代碼解釋:
typeof(Storage) 將輸出function, typeof(localStorage) 將輸出Object,也有說(shuō)要添加 typeof(window.localStorage)的。增強(qiáng)檢測(cè),我覺(jué)得沒(méi)太大必要。另外,localStorage其實(shí)就是一個(gè)對(duì)象,因此我們存儲(chǔ),都是往這個(gè)對(duì)象中增加鍵值對(duì)而已。
localStorage數(shù)據(jù)的“全局性“
? 此處說(shuō)全局性,大家可別以為是全局變量,這是不同的概念。localStorage的數(shù)據(jù)就數(shù)據(jù)本身來(lái)說(shuō),其實(shí)是脫離程序而存在的(磁盤中不同的程序所產(chǎn)生的localStorage會(huì)被分離存放,不會(huì)互相干擾),那么,它就不受程序作用域范圍的限制,即,擁有全局性。既然如此,我們可以有以下用法:
統(tǒng)計(jì)用戶頁(yè)面訪問(wèn)次數(shù)
html代碼
<div class="box">
<p>當(dāng)前訪問(wèn)人次:<span id="views"></span></p>
<p>TIP:關(guān)閉或刷新,訪問(wèn)次數(shù)會(huì)增加。</p>
</div>
javascript代碼
if (localStorage.views) {
localStorage.views = Number(localStorage.views) + 1;
} else {
localStorage.setItem("views", 1);
}
document.getElementById("views").innerHTML = localStorage.views;
效果展示

sessionStorage 定義
?關(guān)于sessionStorage的解釋都比較統(tǒng)一:sessionStorage方法 針對(duì)一個(gè) session【會(huì)話】進(jìn)行數(shù)據(jù)存儲(chǔ)。當(dāng)用戶關(guān)閉瀏覽器窗口后,數(shù)據(jù)會(huì)被刪除。sessionStorage數(shù)據(jù)信息是存儲(chǔ)在內(nèi)存中的。
sessionStorage 的使用
?sessionStorage與localStorage的用法類似,也有setItem() 和 getItem()。
?下面我們來(lái)看一個(gè)案例
html代碼
<div class="box">
<button id="click">點(diǎn)擊計(jì)數(shù)</button>
<p>當(dāng)前計(jì)數(shù):<span id="views"></span></p>
</div>
javascript代碼
if (sessionStorage.views) {
// todo
} else {
sessionStorage.setItem("views", 1);
}
document.getElementById("click").onclick = function() {
sessionStorage.views = Number(sessionStorage.views) + 1;
document.getElementById("views").innerHTML = sessionStorage.views;
}
效果展示

在該案例中,我們用dom操作給 views 綁定了點(diǎn)擊事件,每次點(diǎn)擊,增加一個(gè)計(jì)數(shù),變量存放在session中。
驗(yàn)證什么是一次「會(huì)話」
看這個(gè)例子
html代碼
<div class="box">
<button id="click">點(diǎn)擊計(jì)數(shù)</button>
<p>當(dāng)前訪問(wèn)人次:<span id="views"></span></p>
<p>TIP:刷新,訪問(wèn)次數(shù)會(huì)增加;關(guān)閉頁(yè)面,訪問(wèn)次數(shù)會(huì)重置。</p>
</div>
javascript代碼
if (sessionStorage.views) {
sessionStorage.views = Number(sessionStorage.views) + 1;
} else {
sessionStorage.setItem("views", 1);
}
document.getElementById("views").innerHTML = sessionStorage.views;
效果展示

?
?所以說(shuō):一次會(huì)話是指:用戶打開(kāi)瀏覽器,點(diǎn)擊多個(gè)超鏈接,訪問(wèn)Web服務(wù)器上的資源,然后關(guān)閉瀏覽器,整個(gè)過(guò)程稱之為一次會(huì)話。也就是說(shuō),刷新不會(huì)提前關(guān)閉會(huì)話。
關(guān)于瀏覽器存儲(chǔ),大致就這些,接下來(lái)我們?cè)诳纯礊g覽器緩存
?
* 應(yīng)用緩存 - 瀏覽器緩存
什么是應(yīng)用緩存?
「緩存」 就是當(dāng)你打開(kāi)一個(gè)網(wǎng)頁(yè)時(shí),瀏覽器會(huì)自動(dòng)下載副本到本地電腦上,感覺(jué)就像是你“另存為“一個(gè)網(wǎng)頁(yè)到某個(gè)地方。瀏覽器也不是把所有的網(wǎng)頁(yè)都緩存到本地,一般html或get請(qǐng)求會(huì)緩存,而post就不緩存。
控制是否緩存
?1. 客戶端是否需要緩存能夠在服務(wù)器端的 響應(yīng)頭上控制,響應(yīng)頭告訴緩存器不要保留緩存,緩存器就不會(huì)緩存相應(yīng)內(nèi)容;
?2. 如果請(qǐng)求信息是需要認(rèn)證或者安全加密的,相應(yīng)內(nèi)容也不會(huì)被緩存;
HTML 5 緩存
HTML 5引入了應(yīng)用緩存【Application Cache】,它能實(shí)現(xiàn)在沒(méi)有因特網(wǎng)連接時(shí)進(jìn)行訪問(wèn)。它有三個(gè)優(yōu)勢(shì):
- 離線瀏覽 - 用戶可以在應(yīng)用離線時(shí)使用它們。
- 速度 - 已緩存資源加載速度更快。
- 減少服務(wù)器負(fù)載 - 瀏覽器將只從服務(wù)器上下載更新過(guò)或更改過(guò)的資源。
如果需要啟用應(yīng)用程序緩存,請(qǐng)?jiān)谖臋n的<html>標(biāo)簽中包含 manifest 屬性:
<DOCTYPE HTML>
<html manifest="demo.appcache">
...
</html>
如上指定了manifest的html文件將會(huì)被緩存,未對(duì)其進(jìn)行指定的頁(yè)面不被緩存。也可以在manifest文件中直接指定該頁(yè)面。
manifest文件的建議拓展名為.appcache。
請(qǐng)注意, manifest 文件需要配置正確的MIME-type,即"text/cache-manifest"必須在 web服務(wù)器上進(jìn)行配置。
MANIFEST.appcache 文件
?manifest 文件是簡(jiǎn)單的文本文件,結(jié)構(gòu)非常簡(jiǎn)單,它告知瀏覽器什內(nèi)容需要緩存,什么內(nèi)容不需要緩存。
由以下三個(gè)部分構(gòu)成:
- CACHE MANIFEST - 在此目錄下列出的文件將在首次下載后進(jìn)行緩存。
- NETWORK - 在此標(biāo)題下列出的文件需要與服務(wù)器交互獲取,不進(jìn)行緩存。
- FALLBACK - 該標(biāo)題下列出的文件規(guī)定當(dāng)頁(yè)面無(wú)法訪問(wèn)時(shí)的回退頁(yè)面(比如404頁(yè)面)
- manifest文件完整實(shí)例*:
CACHE MANIFEST
# 2012-02-21 v1.0.0
/theme.css
/logo.fig
/main.js
NETWORK:
login.html
FALLBACK:
/html5/ /404.html // 前者是資源URI, 后者是代替頁(yè)面
【說(shuō)明:】
- 以 # 開(kāi)頭的是注釋行,但也可以滿足其他需求。應(yīng)用緩存會(huì)在器 manifest 文件被更改的時(shí)候更新。如果您編輯了一副圖片,或者修改了一個(gè)javascript函數(shù),這些改變都不會(huì)被重新緩存。這時(shí)候,更新注釋行中的日期和版本號(hào)是一種使瀏覽器重新緩存文件的非常好的辦法。
- NETWORK 可以使用星號(hào)來(lái)指示所有其他資源/文件都需要因特網(wǎng)連接,如
NETWORK:
*
- 更新緩存:
1. 用戶在瀏覽器上自己清空緩存。
2. manifest 文件被修改。
3. 由程序來(lái)更新應(yīng)用緩存。
經(jīng)常遇到的困擾:
? 一旦文件被緩存,則瀏覽器會(huì)繼續(xù)展示已緩存的版本。你可能會(huì)遇到,服務(wù)器上已經(jīng)更新了代碼,但瀏覽器依舊顯示舊的內(nèi)容,而且已經(jīng)向CDN多次推新的資源也沒(méi)用。 其實(shí)這時(shí)候就是因?yàn)闉g覽器緩存了的原因。你需要更新一下manifest文件。一般瀏覽器設(shè)置的限制緩存是5M。
?
* 從瀏覽器角度看緩存
借用網(wǎng)絡(luò)上的一張圖片:

我們來(lái)細(xì)說(shuō)兩個(gè)校驗(yàn)參數(shù):
Last-Modified 和 ETag
1. Last-Modified 工作原理
?在瀏覽器第一次請(qǐng)求某一個(gè)URL時(shí),服務(wù)器端的返回狀態(tài)會(huì)是200,內(nèi)容是你請(qǐng)求的資源,同時(shí)有一個(gè)Last-Modified的屬性標(biāo)記(HttpReponse Header)此文件在服務(wù)期端最后被修改的時(shí)間.
?格式:Last-Modified:Tue, 24 Feb 2009 08:01:04 GMT
?客戶端第二次請(qǐng)求此URL時(shí),根據(jù)HTTP協(xié)議的規(guī)定,瀏覽器會(huì)向服務(wù)器發(fā)送If-Modified-Since報(bào)頭(HttpRequest Header),詢問(wèn)該時(shí)間之后文件是否有被修改過(guò):
?格式:If-Modified-Since:Tue, 24 Feb 2009 08:01:04 GMT
?如果服務(wù)器端的資源沒(méi)有變化,則自動(dòng)返回HTTP304(NotChanged.)狀態(tài)碼,內(nèi)容為空,這樣就節(jié)省了傳輸數(shù)據(jù)量。當(dāng)服務(wù)器端代碼發(fā)生改變或者重啟服務(wù)器時(shí),則重新發(fā)出資源,返回和第一次請(qǐng)求時(shí)類似。從而保證不向客戶端重復(fù)發(fā)出資源,也保證當(dāng)服務(wù)器有變化時(shí),客戶端能夠得到最新的資源。
注:如果If-Modified-Since的時(shí)間比服務(wù)器當(dāng)前時(shí)間(當(dāng)前的請(qǐng)求時(shí)間request_time)還晚,會(huì)認(rèn)為是個(gè)非法請(qǐng)求。
2. ETag 工作原理
?HTTP協(xié)議規(guī)格說(shuō)明定義ETag為“被請(qǐng)求變量的實(shí)體標(biāo)記”,簡(jiǎn)單說(shuō)即服務(wù)器響應(yīng)時(shí)給請(qǐng)求URL標(biāo)記,并在HTTP響應(yīng)頭中將其傳送到客戶端,類似服務(wù)器端返回的格式:
?格式:Etag:“5d8c72a5edda8d6a:3239″
?客戶端的查詢更新格式是這樣的:
?格式:If-None-Match:“5d8c72a5edda8d6a:3239″
如果ETag沒(méi)改變,則返回狀態(tài)304。
即:在客戶端發(fā)出請(qǐng)求后,HttpReponse Header中包含Etag:“5d8c72a5edda8d6a:3239″標(biāo)識(shí),等于告訴Client端,你拿到的這個(gè)的資源有表示ID:5d8c72a5edda8d6a:3239。當(dāng)下次需要發(fā)Request索要同一個(gè)URI的時(shí)候,瀏覽器同時(shí)發(fā)出一個(gè)If-None-Match報(bào)頭(Http RequestHeader)此時(shí)包頭中信息包含上次訪問(wèn)得到的Etag:“5d8c72a5edda8d6a:3239″標(biāo)識(shí)。
?格式:If-None-Match:“5d8c72a5edda8d6a:3239“
?這樣,Client端等于Cache了兩份,服務(wù)器端就會(huì)比對(duì)2者的etag。如果If-None-Match為False,不返回200,返回304(Not Modified) Response。
就介紹這些,如果有錯(cuò)誤,歡迎指正。