JavaScript 高級(jí)程序設(shè)計(jì)(第23 離線應(yīng)用與客戶端存儲(chǔ))

第23 離線應(yīng)用與客戶端存儲(chǔ)

1. 離線檢測(cè)

(1)navigator.onLine 屬性,這個(gè)屬性值為true表示設(shè)備能上網(wǎng),值為false表示設(shè)備離線。
(2)兩個(gè)事件: online 和 offline。當(dāng)網(wǎng)絡(luò)從離線變?yōu)樵诰€或者從在線變?yōu)殡x線時(shí),分別觸發(fā)這兩個(gè)事件。這兩個(gè)事 件在 window 對(duì)象上觸發(fā)。

2. 應(yīng)用緩存

(1) HTML5 的應(yīng)用緩存(application cache),或者簡(jiǎn)稱為 appcache,是專門為開發(fā)離線 Web 應(yīng)用而設(shè)計(jì) 的。Appcache 就是從瀏覽器的緩存中分出來的一塊緩存區(qū)。要想在這個(gè)緩存中保存數(shù)據(jù),可以使用一個(gè)描述文件(manifest file),列出要下載和緩存的資源。
(2) 要將描述文件與頁面關(guān)聯(lián)起來,可以在<html>中的 manifest 屬性中指定這個(gè)文件的路徑<htmlmanifest="/offline.manifest">
這個(gè)文件的 MIME 類型必須是 text/cache-manifest1。
(3) applicationCache 對(duì)象,這個(gè)對(duì)象有一個(gè) status 屬性,屬性的值是常量,表示應(yīng)用緩存的如下當(dāng)前狀態(tài)。

  • 0:無緩存,即沒有與頁面相關(guān)的應(yīng)用緩存。
  • 1:閑置,即應(yīng)用緩存未得到更新。
  • 2:檢查中,即正在下載描述文件并檢查更新。
  • 3:下載中,即應(yīng)用緩存正在下載描述文件中指定的資源。
  • 4:更新完成,即應(yīng)用緩存已經(jīng)更新了資源,而且所有資源都已下載完畢,可以通過 swapCache()來使用了。
  • 5:廢棄,即應(yīng)用緩存的描述文件已經(jīng)不存在了,因此頁面無法再訪問應(yīng)用緩存。

(4) 應(yīng)用緩存還有很多相關(guān)的事件,表示其狀態(tài)的改變。以下是這些事件。

  • checking:在瀏覽器為應(yīng)用緩存查找更新時(shí)觸發(fā)。
  • error:在檢查更新或下載資源期間發(fā)生錯(cuò)誤時(shí)觸發(fā)。
  • noupdate:在檢查描述文件發(fā)現(xiàn)文件無變化時(shí)觸發(fā)。
  • downloading:在開始下載應(yīng)用緩存資源時(shí)觸發(fā)。
  • progress:在文件下載應(yīng)用緩存的過程中持續(xù)不斷地觸發(fā)。
  • updateready:在頁面新的應(yīng)用緩存下載完畢且可以通過 swapCache()使用時(shí)觸發(fā)。
  • cached:在應(yīng)用緩存完整可用時(shí)觸發(fā)

(5) update()方法也可以 手工干預(yù),讓應(yīng)用緩存為檢查更新而觸發(fā)上述事件。applicationCache.update();
(6) 如果觸發(fā)了 updateready 事件,則說明新版本的應(yīng)用緩存已經(jīng)可用,而此時(shí)你需 要調(diào)用swapCache()來啟用新應(yīng)用緩存

EventUtil.addHandler(applicationCache, "updateready", function(){ 
applicationCache.swapCache();
});

3. 數(shù)據(jù)存儲(chǔ)

(1) Cookie

  1. HTTP Cookie,通常直接叫做 cookie,最初是在客戶端用于存儲(chǔ)會(huì)話信息的。該標(biāo)準(zhǔn)要求服務(wù)器對(duì)任意 HTTP 請(qǐng)求發(fā)送 Set-Cookie HTTP 頭作為響應(yīng)的一部分,其中包含會(huì)話信息。
  2. 瀏覽器會(huì)存儲(chǔ)這樣的會(huì)話信息,并在這之后,通過為每個(gè)請(qǐng)求添加Cookie HTTP 頭將信 息發(fā)送回服務(wù)器。
* 限制

cookie 在性質(zhì)上是綁定在特定的域名下的。當(dāng)設(shè)定了一個(gè) cookie 后,再給創(chuàng)建它的域名發(fā)送請(qǐng)求時(shí), 都會(huì)包含這個(gè) cookie。這個(gè)限制確保了儲(chǔ)存在 cookie 中的信息只能讓批準(zhǔn)的接受者訪問,而無法被其他 域訪問。

  1. 每個(gè)域的 cookie 總數(shù)是有限的,不過瀏覽器之間各有不同。
  2. 瀏覽器中對(duì)于 cookie 的尺寸也有限制。大多數(shù)瀏覽器都有大約 4096B(加減 1)的長(zhǎng)度限制。
*cookie 的構(gòu)成

cookie 由瀏覽器保存的以下幾塊信息構(gòu)成:

  1. 名稱(name):一個(gè)唯一確定 cookie 的名稱。cookie 名稱是不區(qū)分大小寫的,所以 myCookie 和 MyCookie 被認(rèn)為是同一個(gè) cookie。然而,實(shí)踐中最好將 cookie 名稱看作是區(qū)分大小寫的,因?yàn)槟承┓?wù)器會(huì)這樣處理 cookie。cookie 的名稱必須是經(jīng)過 URL 編碼的。
  2. 值:儲(chǔ)存在 cookie 中的字符串值。值必須被 URL 編碼。
  3. 域(domain):cookie 對(duì)于哪個(gè)域是有效的。所有向該域發(fā)送的請(qǐng)求中都會(huì)包含這個(gè) cookie 信息。這個(gè)值
    可以包含子域(subdomain,如 www.wrox.com),也可以不包含它(如.wrox.com,則對(duì)于 wrox.com的所有子域都有效)。如果沒有明確設(shè)定,那么這個(gè)域會(huì)被認(rèn)作來自設(shè)置 cookie 的那個(gè)域。
  4. 路徑(path):對(duì)于指定域中的那個(gè)路徑,應(yīng)該向服務(wù)器發(fā)送 cookie。例如,你可以指定 cookie 只有從 http://www.wrox.com/books/ 中才能訪問,那么 http://www.wrox.com 的頁面就不會(huì)發(fā)送 cookie 信息,即使請(qǐng)求都是來自同一個(gè)域的。
  5. 失效時(shí)間(expires):表示 cookie 何時(shí)應(yīng)該被刪除的時(shí)間戳(也就是,何時(shí)應(yīng)該停止向服務(wù)器發(fā)送這個(gè)
    cookie)。默認(rèn)情況下,瀏覽器會(huì)話結(jié)束時(shí)即將所有 cookie 刪除;不過也可以自己設(shè)置刪除時(shí)間。 這個(gè)值是個(gè) GMT 格式的日期(Wdy, DD-Mon-YYYY HH:MM:SS GMT),用于指定應(yīng)該刪除 cookie 的準(zhǔn)確時(shí)間。因此,cookie 可在瀏覽器關(guān)閉后依然保存在用戶的機(jī)器上。如果你設(shè)置的失 效日期是個(gè)以前的時(shí)間,則 cookie 會(huì)被立刻刪除。
  6. 安全標(biāo)志(secure):指定后,cookie 只有在使用 SSL 連接的時(shí)候才發(fā)送到服務(wù)器。例如,cookie 信息只 能發(fā)送給 https://www.wrox.com,而 http://www.wrox.com 的請(qǐng)求則不能發(fā)送 cookie
每一段信息都作為 Set-Cookie 頭的一部分,使用分號(hào)加空格分隔每一段

Set-Cookie: name=value; expires=Mon, 22-Jan-07 07:10:24 GMT; domain=.wrox.com

*JavaScript 中的 cookie
document. cookie 屬性。
  1. 當(dāng)用來獲取屬性值時(shí), document.cookie 返回當(dāng)前頁面可用的(根據(jù) cookie 的域、路徑、失效時(shí)間和安全設(shè)置)所有 cookie 的字符串,一系列由分號(hào)隔開的名值對(duì)兒.
  2. 當(dāng)用于設(shè)置值的時(shí)候,document.cookie 屬性可以設(shè)置為一個(gè)新的 cookie 字符串。這個(gè) cookie 字
    符串會(huì)被解釋并添加到現(xiàn)有的 cookie 集合中。設(shè)置 document.cookie 并不會(huì)覆蓋 cookie,除非設(shè)置的cookie 的名稱已經(jīng)存在。
*子 cookie

子 cookie 是存放在單個(gè) cookie 中的更小段的數(shù)據(jù)。也就是使用 cookie 值來存儲(chǔ)多個(gè)名稱值對(duì) 兒。子 cookie 最常見的的格式如下所示。
name=name1=value1&name2=value2&name3=value3&name4=value4

(2) IE用戶數(shù)據(jù)

在 IE5.0 中,微軟通過一個(gè)自定義行為引入了持久化用戶數(shù)據(jù)的概念。用戶數(shù)據(jù)允許每個(gè)文檔最多 128KB 數(shù)據(jù),每個(gè)域名最多 1MB 數(shù)據(jù)。要使用持久化用戶數(shù)據(jù),首先必須如下所示,使用 CSS 在某個(gè) 元素上指定 userData 行為:
<div style="behavior:url(#default#userData)" id="dataStore"></div>

  1. 使用 setAttribute()方法保存數(shù)據(jù)。
  2. 為了將數(shù)據(jù)提交到瀏覽器緩存中,還必須調(diào)用save()方法并告訴它要保存到的數(shù)據(jù)空間的名字。數(shù)據(jù)空間名字可以完全任意,僅用于區(qū)分不同的數(shù)據(jù)集。
var dataStore = document.getElementById("dataStore");
dataStore.setAttribute("name", "Nicholas");
dataStore.setAttribute("book", "Professional JavaScript");
dataStore.save("BookInfo");
  1. 下一次頁面載入之后,可以使用 load()方法指定 同樣的數(shù)據(jù)空間名稱來獲取數(shù)據(jù)。
  2. getAttribute()調(diào)用了不存在的名稱或者是尚未載入的名 稱,則返回 null。
dataStore.load("BookInfo");
alert(dataStore.getAttribute("name")); //"Nicholas"
alert(dataStore.getAttribute("book")); //"Professional JavaScript"
  1. 通過removeAttribute()方法明確指定要?jiǎng)h除某元素?cái)?shù)據(jù),只要指定屬性名稱。刪除之后, 必須像下面這樣再次調(diào)用 save()來提交更改。
 dataStore.removeAttribute("name");
dataStore.removeAttribute("book");
dataStore.save("BookInfo");

(3) Web存儲(chǔ)機(jī)制

*Storage 類型
  1. clear(): 刪除所有值;Firefox 中沒有實(shí)現(xiàn) 。
  2. getItem(name):根據(jù)指定的名字 name 獲取對(duì)應(yīng)的值。
  3. key(index):獲得 index 位置處的值的名字。
  4. removeItem(name):刪除由 name 指定的名值對(duì)兒。
  5. setItem(name, value):為指定的 name 設(shè)置一個(gè)對(duì)應(yīng)的值。
*sessionStorage 對(duì)象

sessionStorage對(duì)象存儲(chǔ)特定于某個(gè)會(huì)話的數(shù)據(jù),也就是該數(shù)據(jù)只保持到瀏覽器關(guān)閉。

  1. sessionStorage 對(duì)象其實(shí)是 Storage 的一個(gè)實(shí)例,所以可以使用 setItem()或者直接設(shè)。
  2. sessionStorage 中有數(shù)據(jù)時(shí),可以使用 getItem()或者通過直接訪問屬性名來獲取數(shù)據(jù)。
  3. 可以通過結(jié)合 length 屬性和 key()方法來迭代 sessionStorage 中的值。
  4. 可以使用 for-in 循環(huán)來迭代 sessionStorage 中的值。
  5. 可以使用 delete 操作符刪除對(duì)象屬性,也可調(diào)用 removeItem()方法。
*globalStorage 對(duì)象

globalStorage這個(gè)對(duì)象的目的是跨越會(huì)話存儲(chǔ)數(shù)據(jù),但有特定的訪問限制。要使用 globalStorage,首先要指定哪些域可以訪問該數(shù)據(jù)??梢酝ㄟ^方括號(hào)標(biāo)記使用屬性來實(shí)現(xiàn)。

  1. 對(duì) globalStorage 空間的訪問,是依據(jù)發(fā)起請(qǐng)求的頁面的域名、協(xié)議和端口來限制的。
  2. 如果你事先不能確定域名,那么使用 location.host作為屬性名比較安全。
  3. 如果不使用 removeItem()或者 delete 刪除,或者用戶未清除瀏覽器緩存,存儲(chǔ)在 globalStorage 屬性中的數(shù)據(jù)會(huì)一直保留在磁盤上。
*localStorage 對(duì)象

不能給localStorage指定任何訪問規(guī)則;規(guī)則事先就設(shè)定好了。要訪問同一個(gè) localStorage 對(duì)象,頁面必須來自同一個(gè)域名(子域名無效),使用同一種 協(xié)議,在同一個(gè)端口上。這相當(dāng)于 globalStorage[location.host]

*storage 事件

這個(gè)事件的 event 對(duì)象有以下屬性。
(1) domain:發(fā)生變化的存儲(chǔ)空間的域名。
(2) key:設(shè)置或者刪除的鍵名。
(3) newValue:如果是設(shè)置值,則是新值;如果是刪除鍵,則是 null。
(4) oldValue:鍵被更改之前的值。

(4) IndexedDB

*數(shù)據(jù)庫

IndexedDB 最大的特色是使用對(duì)象保存數(shù)據(jù),而不是使用表來保存數(shù)據(jù)。一個(gè) IndexedDB 數(shù)據(jù)庫,就是 一組位于相同命名空間下的對(duì)象的集合。

var indexedDB = window.indexedDB || window.msIndexedDB || window.mozIndexedDB || window.webkitIndexedDB;
  1. 把要打開的數(shù)據(jù)庫名傳給indexDB.open()。如果傳入的 數(shù)據(jù)庫已經(jīng)存在,就會(huì)發(fā)送一個(gè)打開它的請(qǐng)求;如果傳入的數(shù)據(jù)庫還不存在,就會(huì)發(fā)送一個(gè)創(chuàng)建并打開 它的請(qǐng)求??傊?調(diào)用 indexDB.open()會(huì)返回一個(gè) IDBRequest 對(duì)象,在這個(gè)對(duì)象上可以添加 onerror 和 onsuccess 事件處理程序。
var request, database;
request = indexedDB.open("admin");
request.onerror = function(event){
    alert("Something bad happened while trying to open: " +
           event.target.errorCode);
};
request.onsuccess = function(event){
    database = event.target.result;
};

(1) event.target.result中將有一個(gè)數(shù)據(jù)庫實(shí)例對(duì)象(IDBData- base),這個(gè)對(duì)象會(huì)保存在 database 變量中。
(2) 如果發(fā)生了錯(cuò)誤,那 event.target.errorCode中將 保存一個(gè)錯(cuò)誤碼,表示問題的性質(zhì)。

  1. 默認(rèn)情況下,IndexedDB 數(shù)據(jù)庫是沒有版本號(hào)的,最好一開始就為數(shù)據(jù)庫指定一個(gè)版本號(hào)。為此, 可以調(diào)用setVersion()方法,傳入以字符串形式表示的版本號(hào)。
最后編輯于
?著作權(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)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • ??支持離線 Web 應(yīng)用開發(fā)是 HTML5 的另一個(gè)重點(diǎn)。 ??所謂離線 Web 應(yīng)用,就是在設(shè)備不能上網(wǎng)的情況...
    霜天曉閱讀 1,185評(píng)論 0 2
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,525評(píng)論 19 139
  • 支持離線web應(yīng)用開發(fā)是HTML5的另一個(gè)重點(diǎn)。所謂離線web應(yīng)用,就是在設(shè)備不能上網(wǎng)的情況下仍然可以運(yùn)行的應(yīng)用。...
    __越過山丘__閱讀 205評(píng)論 0 1
  • 開發(fā)離線Web應(yīng)用的步驟:1.檢測(cè)設(shè)備是否可以上網(wǎng);2.能訪問一定的資源;3.有一塊本地空間保存數(shù)據(jù)。 1. 離線...
    xiaoguo16閱讀 407評(píng)論 2 3
  • 在寫這篇文章之前,我重新翻閱了自己的日記。從學(xué)習(xí)累積法開始到現(xiàn)在,我發(fā)現(xiàn)自己在不斷地調(diào)整,從前認(rèn)為重要的事情,到現(xiàn)...
    爬行中的小蝸牛閱讀 642評(píng)論 2 3

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