客戶端存儲web應用容許使用瀏覽器提供的API實現將數據存儲在用戶電腦上。javascript
客戶端存儲遵循「同源策略」,所以不一樣站點的頁面是沒法讀取對於存儲的數據。而同一站點的不一樣的頁面之間是能夠互相共享存儲數據的。css
同源策略能夠拿localStorage來說,以下:html
打開http://www.w3school.com.cn/html5
打開http://www.w3school.com.cn/html5/index.aspjava
數據都是保存在對應的域名http://www.w3school.com.cn/下的,當域名同源的時候,是能夠訪問到保存下來的數據的。程序員
web應用能夠選擇他們存儲數據的有效期:有臨時存儲的,可讓數據保存至當前窗口關閉或瀏覽器退出;也有永久存儲,能夠將數據永久地存儲在硬盤上,數年或者數月不失效。web
web存儲正則表達式
先是HTML5的一個API,後來成了標準了。目前包含IE8在內的主流瀏覽器(可交互地)都實現了。包含localStorage和sessionStorage對象,這兩個對象其實是持久化的關聯數組,是名值對的映射表,「名」和「值」都是字符串。web存儲易於使用,支持大容量(但非無限量)數據存儲同時兼容當前全部主流瀏覽器(但不兼容早期瀏覽器)算法
cookiechrome
cookie是一種早期的客戶端存儲機制,期初是爲徵對服務器端腳本設計使用的。儘管在客戶端提供了很是繁瑣的javascript API來操做cookie,但它們難用至極,並且只適合少許的文本存儲。不只如此,任何以cookie形式存儲的數據,不論服務器端是否須要,每一次HTTP請求都要把這些數據傳輸到服務器端。cookie目前仍然被大量的客戶端程序員使用的一個重要的緣由是:全部新舊瀏覽器都支持它。可是,隨着Web Storage的普及,cookie將最終迴歸到最初的形態:做爲一種被服務端腳本使用的客戶存儲機制。
IE User Data
微軟在IE5以後的IE瀏覽器實現了專屬它的客戶端存儲機制-「User Data」。userData能夠實現必定量的字符串數據存儲,對於IE8前的IE瀏覽器,能夠將其用作是Web存儲的替代方案。
離線web應用
HTML5標準定義了一組「離線web應用」API,用於緩存web頁面以及相關資源(圖片,腳本,CSS文件等)。它的現實是將web應用總體存儲在客戶端,而不只是存儲數據。它可以讓web應用「安裝」在客戶端。這樣一來,哪怕網絡不可用的時候web應用依然是可用的。
web數據庫
爲了可以讓開發者像使用數據那樣操做大量的數據,不少主流瀏覽器紛紛實如今其中開始集成客戶端數據庫功能。Safari,Chrome,和Opera都內置了SQL數據庫的客戶端API。遺憾的是這類的API標準化最終以失敗而了結,而且,Firefox和IE看來不打算實現這類API。目前還有一種正在標準化的API,稱爲「索引數據庫API」。調用該API返回的是一個不包含查詢術語的簡單數據庫對象。這兩種客戶端數據庫API都是異步的,都使用了事件處理機制(相似DOM事件的機制),這樣的方式多多少少都顯得複雜。
文件系統API
前面介紹過現代的瀏覽器都支持一個文件對象,用以將選擇的文件經過xmlHttPRequest上傳到服務器。與之相關的規範(草案階段)定義了一組API,用於操做一個私有的本地文件系統。該系統中,能夠進行對文件的讀寫操做。目前正在標準化當中。
web瀏覽器一般會提供「記住密碼」功能,這些密碼會以加密的形式安全地存儲在硬盤上。然而本章介紹的任何形式客戶端數據存儲都不牽扯加密:任何存儲在用戶硬盤上的數據都是未加密形式。這樣一來,對於擁有電腦訪問權限的惡意用戶或者惡意軟件一樣也能夠得到存儲的數據。所以,任何形式的客戶端存儲都不該該用來保存密碼、商業帳號或者相似的敏感信息。
還要記住一點:不少web用戶不信任那些使用cookie和其它客戶端存儲機制來作相似「跟蹤」功能的網站。因此,儘可能嘗試本章討論的存儲機制來網站升級用戶體驗;而不是用它們來收集和侵犯隱私相關的數據。若是網站濫用客戶端存儲,用戶將禁用該功能。這樣一來不只達不到效果,還會致使依賴客戶端存儲的網站徹底不可用。
實現了「web存儲」草案標準的瀏覽器在window對象上定義了兩個屬性,localStorage和sessionStorage。在控制檯輸入window.localStrage能夠得到頁面所存儲的數據。
這兩個屬性表明同一個Storage對象——一個持久化關聯數組,數組使用字符串來索引,存儲的值也是字符串形式的,Storage對象在使用上和通常的Javascript沒有什麼兩樣,設置對象的屬性爲字符串值,隨後瀏覽器會將值存儲起來。lcoalStorage和sessionStorage二者的區別在於存儲的有效期和做用域不一樣:數據能夠存儲多長時間及擁有數據的訪問權。
示例:localStorage和sessionStorage相似
var name = localStorage.username; //查詢一個存儲的值 name = localStorage["username"]; //等於數組表示法 if (!name) { name = prompt("請輸入你的名字"); //詢問用戶一個答案 localStorage.username = name; //存儲用戶的答案 } //迭代全部存儲的name/value對 for (var name in localStorage) { //迭代全部存儲的名字 var value = localStorage[name]; //查詢每一個名字對應的值 }
Storage對象還定義了一些諸如存儲、獲取、遍歷和刪除的方法。
「web存儲」草案標準指出,咱們既能夠存儲結構化的數據(對象和數組),也能夠存儲原始類型數據,還能夠存儲諸如日期、正則表達式甚至是文件對象在內的內置類型和數據。(在一些瀏覽器中,僅僅支持存儲字符串類型數據,若是要存儲和其它類型的書,不得不本身手動進行和編碼解碼),以下例子所示:
//當存儲一個數字的時候,會自動轉換成一個字符串 //可是,當獲取該值的時候,別忘了手動轉換成數字類型 localStorage.x = 10; var x = parseInt(localStorage.x); //一樣,存儲一個日期類型數據的時候進行編碼,獲取的時候進行解碼 localStorage.lastRead = (new Date()).toUTCString(); var lastdate = new Date(Date.parse(localStorage.lastRead)); //使用JSON可使得對基本數據類型的編碼規則變得很方法 var data = new Date(); localStorage.data = JSON.stringify(data)//編碼後存儲 var data = JSON.parse(localStorage.data)//獲取數值後再解碼
經過localStorage存儲的數據是永久性的,除非web應用馬上刪除存儲的數據。或者用戶經過設置瀏覽器配置(瀏覽器提供的特定UI)來刪除,不然數據將一直保留在用戶電腦上,永不過時。
localStorage的做用域是限定在文檔源(document origin)級別的。文檔源是經過協議、主機名及端口三者來肯定的。所以,每一個url都有不一樣的文檔源。
同源文檔間共享localStorage數據(不論該源的腳本是否真正的訪問的localStorage)。它們能夠互相讀取對方的數據,甚至能夠覆蓋對方的數據。可是,非同源的文檔見互相都不能讀取和共享或覆蓋對方的數據(即便它們的腳原本自同一臺第三方服務器也不行)。
須要注意的是localStorage的做用域也收到瀏覽器供應商的限制。若是你使用的Firefox訪問站點那麼下一次用另一個瀏覽器打開的時候,那麼本次是沒法獲取上次的數據的。
sessionStorage的有效期和存儲數據的腳本所在最頂層的窗口或者是瀏覽器標籤頁是同樣的。一旦窗口或者標籤頁被永久關閉了,那麼全部經過sessionStorage存儲的數據也被刪除了(須要注意的是,現代的瀏覽器具有了一些關閉標籤頁隨後恢復上一次瀏覽器回話的功能,可能預知相關的sessionStorage會更長些)。
做用域也是限定在文檔源中,所以,非同源的文檔之間是沒法貢獻sessionStorage的。不只如此,sessionStorage的做用域還被限定在窗口中。若是同源的文檔渲染在不一樣的瀏覽器標籤頁中,那麼他們互相之間擁有的是各自的sessionStorage數據,沒法共享。就是說,同個瀏覽器下兩個相同的標籤頁也不能共享數據。
須要注意的是:這裏提到的基於窗口做用域的sessionStorage指的窗口是頂級窗口。若是一個瀏覽器標籤包含兩個<iframe>元素,它們是同源的,那麼二者之間是能夠共享的sessionStorage的。
localStorage和sessionStorage一般是被當作普通的javascript對象使用。經過設置屬性來存儲字符串值,查詢該屬性來讀取該值。這兩個對象還提供了兩個正式的API。
setItem()
getItem()
removeItem()(在非IE8的瀏覽器中,還可使用delete操做符來刪除數據,就和普通對象使用的delete操做符同樣)
clear()(不須要參數)
使用length和key()方法,傳入0~length~1的數字,能夠枚舉全部存儲數據的名字。
示例:
localStorage.setItem("x", 1); //以"x"的名字存儲一個數值 localStorage.getItem("x"); //獲取x的數值 //枚舉全部的存儲的名字/值對 for(var i = 0;i<localStorage.length;i++){//length 表示了全部名字/值對 var name = localStorage.key(i); //獲取第i對的名字 var value = localStorage.getItem(name);//獲取該對的值 } localStorage.removeItem("x")//刪除"x"項 localStorage.clear();//所有刪除
若是瀏覽器提供商徹底實現了「web存儲」的標準,只對對象和數組類型的數據存儲,那麼就會又多了一個使用相似用setItem()和getItem()這類方法的理由。對象和數組的值一般是可變的,所以存儲對象要求存儲它們的副本,以確保以後對任何這類對象的改變不影響到存儲的對象。一樣的 ,在獲取該對象的時候,也要求獲取是該對象的副本,以確保已獲取的對象的改動不會影響到存儲的對象。而這類操做若是若是使用基於屬性的API就會使人困惑。考慮以下這段代碼(假設瀏覽器已經支持告終構化數據存儲)。
localStorage.o = {x:1};//存儲一個帶有"x"屬性的對象 localStorage.o.x = 2; //試圖設置該對象的屬性值 localStorage.o.x; //=>undefined x沒有改變
......
目前還沒徹底實現這個標準呢。
不管何時,存儲在localStorage或者sessionStorage的數據發生改變,瀏覽器都會在其它對該數據可見的窗口對象上出發存儲事件(可是在對數據改變的窗口上是不出發的)。若是瀏覽器有兩個標籤頁都打開了來自於同源的頁面,其中一個在localStorage上存儲了數據,那麼在另一個標籤頁就會接受到一個存儲事件。要記住,sessionStorage的做用域是限制在頂層窗口的,所以對於sessionStorage的改變只有相關牽連的窗口才會觸發存儲事件。像給已經存在的存儲項設置一個如出一轍的值,或者是刪除一個原本就不存在的項存儲都是不會觸發存儲事件的。
爲存儲事件註冊處理程序能夠經過addEventListener()方法,(或者在IE下使用attachEvent方法)。在絕大多瀏覽器中,還能夠給Window對象設置onstorage屬性的方法,不過Firefox不支持該屬性。
與事件相關的事件對象有5個很是重要的屬性(遺憾的是IE8不支持他們)
key:被設置或移除項的鍵名。若是調用clear()函數,那麼該屬性值就爲null.
newValue:保存該項新值;或者調用removeItem()時,該屬性值爲null。
oldvalue:改變或刪除該項前,保存該項的原先值;當插入一個新項的時候,該屬性值爲null
storageArea:這個屬性值就比如目標window對象上的locaStorage屬性或者是sessionStorgae屬性
url:觸發該存儲變化腳本所在的文檔URL
最後,要注意的是:localStorage和sessionStorage存儲機制都是廣播機制的,瀏覽器會對目前正在訪問的同源站點全部窗口發送消息。舉個例子:若是一個用戶要求網站中止動畫效果時,那麼該站點可能會在localStorage中存儲該用戶的首選項,這樣依賴,之後再訪問該站點的時候自動中止該動畫效果了。由於存儲了首選項,致使觸發的一個存儲事件讓其它的同源頁面也得到了一個用戶請求。再好比,一個機遇web的圖片編輯應用,一般容許在其它窗口中展示工具條。當用戶選擇一個工具的時候,應用就可使用localStorage來存儲用戶的當前狀態,而後通知其它的窗口用戶選擇了新的工具。
cookie是指web瀏覽器存儲少許的數據,同時它是與具體的web頁面或者站點相關的。cookie是最先是設計爲被服務端全部的,從底層來看,做爲HTTP協議的一種擴展實現它。cookie數據會自動在web瀏覽器和web服務器之間傳輸的,所以服務端腳本就能夠讀、寫客戶端的cookie值。
能夠經過document.cookie來獲取cookie值。
爲何叫「cookie」?
並沒太多含義。在javascript中,cookie用於保存狀態以及可以爲web瀏覽器提供一種身份識別(密碼等)。可是,javascript中使用cookie不會採起任何加密機制,所以是不安全的。(可是經過https傳說cookie數據是安全的,不過這和cookie自己無關,而和https:協議相關)。
操做cookie的api很早就已經定義和實現了,所以該API的兼容性很好。可是,該API幾乎形同虛設。根本沒有提供諸如查詢、設置、刪除cookie對象的方法,全部這些操做都要經過特殊格式的字符串形式讀寫Document對象的cookie屬性來完成。每一個cookie的有效期和做用域均可以經過cookie屬性分別指定。這些屬性也是經過在同一個cookie上以特殊的字符串來設定的。
檢測cookie是否可用
因爲濫用第三方cookie(如cookie是和網頁上的圖片相關而非網頁自己相關。第三方cookie指的是來自於當前訪問站點覺得的站點設置的cookie)的緣故,致使cookie在大多數web用戶心中有很差的印象。好比,廣告公司能夠利用第三方cookie來實現跟蹤用戶的訪問行爲和習慣,而用戶爲了禁止這種「窺探」用戶隱私的行爲會在它們的瀏覽器中禁用cookie。所以在使用avascript操做cookie前,首先要確保cookie是啓用的。在絕大多數瀏覽器中,可用通檢測過navigator.cookieEnabled這個屬性來實現,若爲true則代表cookie是啓用的。由於該屬性不是一個標準的屬性,因此在不支持該屬性的瀏覽器上,要用下面介紹的cookie技術來讀、寫和刪除cookie數據來測試是否支持cookie。
除了名(name)和值(value),cookie還有一些可選的屬性來控制cookie的有效期和做用域。cookie的默認有效期很短暫;它只在持續在web會話期間,一旦關閉瀏覽器,cookie的保存數據就丟失。須要注意的是這與sessionStorage有效期仍是有區別的,cookie的做用域並非限在瀏覽器的單個窗口中,它的有效期和整個瀏覽器進程不是單個瀏覽器窗口的有效期一一致。若是要延長cookie有效期,能夠經過設置max-age屬性,但必需要明確告訴cookie的有效期是多長,單位是秒。
一旦設置了有效期,瀏覽器就會將cookie數據存儲在一個文件中,而且知道過了指定的有效期纔會刪除該文件。
和localStorage以及sessionStorage相似,cookie的做用域是經過文檔源和文檔路徑來肯定的。該做用域經過cookie的path和domain屬性配置的。在默認的狀況下,cookie和建立它的web頁面有關,並對該web頁面及和該web頁面同目錄或者子目錄其它的頁面可見。好比web頁面http://www.a.com/a/index.html頁面建立了一個cookie,那麼該cookie對http://www.a.com/a/b.html和頁面http://www.a.com/a/b/index.html頁面都是可見的。但對http://www.a.com/c.html是不可見的。
默認的cookie的可見性行爲知足了最多見的需求。不過,有的時候,你可能但願整個網站都使用cookie的值,而無論是那個頁面建立它的。好比用戶在一個頁面表單上輸入了它的郵件地址,你想把它保存下來,爲了避免讓用戶下次回到這個頁面上將其做爲默認的郵件地址。要知足這樣的需求,能夠設置cookie的路徑(設置cookie的path屬性)。
將cookie的路徑設置成"/"等因而讓cookie和localStorage擁有一樣的做用域,同時當它請求該站點上任何一個web頁面的時候,瀏覽器都必須將cookie的名字和值傳遞給服務器。可是須要注意的是,cookie的path屬性不能被用作訪問控制機制。若是一個web頁面想要讀取同一站點其它頁面的cookie,只須要將其餘頁面隱藏<iframe>形式加載進來,隨後讀取對應文檔的cookie就能夠了。同源策略限制了跨站的cookie窺探,可是對同一站點的文檔是徹底合法的。
cookie的做用域默認由文檔源限制。可是,有的大型網站想要子域之間可以相互通訊cookie,這個時候就須要設置coolkie的domian屬性來達到目的。若是http://well.a.com的域下建立了一個cookie,並將其path屬性設置成"/",其domian屬性設置成".a.com",那麼這個cookie就對全部good.a.com,other.a.com以及任何其它a.com域下任何其它服務器均可見。若是沒有爲一個cookie設置域屬性,那麼domian屬性的默認值是當前web服務器的主機名。要注意的是,cookie域只能設置當前服務器的域。
最後要介紹的cookie的屬性是secure,它是一個布爾值屬性,用來代表cookie的值是以何種網絡傳輸。cookie默認是以不安全的形式(經過普通的、不安全的HTTP鏈接)傳遞的。一旦cookie被標識爲「安全的」,那就只能當前瀏覽器和服務器經過https或者其它安全協議鏈接的時候才能傳遞它。
要給當前文檔設置有效的cookie值,很是簡單,只需將cookie屬性設置爲一個字符串的形式的值;
name = value;
以下:
document.cookie = "version=" + encodeURIComponent(document.lastModified);
下次讀取cookie屬性的時候,以前存儲的名/值對的數據就在cookie列表中。因爲cookie的名/值中不容許包含分號、逗號和空白符,所以,在存儲以前通常能夠採用javascript核心的全局函數encodeURIComponent()進行編碼。相應的,讀取cookie值的時候須要採用decodeURICompoent()函數解碼。
以簡單的名/值對形式存儲的cookie數據有效期只在當前的web瀏覽器會話內,一但用戶關閉瀏覽器,cookie數據就丟失了。若是小要延長cookie的有效期,就須要設置max-age屬性來指定cookie的有效期(單位是秒)。按照下面的字符串形式設置cookie的屬性便可。
name = value; max-age = seconds
下面設置一個cookie值,並提供一個max-age屬性
//以名/值對形式存儲cookie //同時採用encodeURIComponet()函數進行編碼,來轉義分號、逗號和空白符 //若是dayTolive是一個數字,設置max-age屬性爲該數值表示cookie知道指定的天數 //到了纔會過時。若是daysTolive是0就表示刪除cookie function setcookie(name, value, daysTolive) { var cookie = name + "=" + encodeURIComponent(value); if (typeof daysTolive === "number") cookie += "; max-age =" + (daysTolive * 60 * 60 * 24); document.cookie = cookie; } setcookie("cook","cool",0);
一樣地,若是要設置cookie的path、domian和secure屬性,只需以下的字符串追加在cookie的值的後面
;path = path ;domain = domian ;secure
要改變cookie的值,須要使用相同的名字、路徑和域,可是新的值從新設置cookie的值。一樣地,設置新max-age屬性就能夠改變cookie的有效期。
要刪除一個cookie,須要使用相同的名字、路徑和域,而後制定一個任意(非空)的值,並將max-age屬性指定爲0,再次設置cookie。
使用javascript表達式來讀取cookie屬性的時候,其返回的值是一個字符串,該字符串都是由一系列的名/值對組成,不一樣名/值對之間經過「分號/空格」分開,其內容包含了全部做用在當前文檔的cookie。可是當它不包含其它設置的cookie屬性。經過document.cookie屬性能夠獲取cookie的值,可是爲了更好地查看cookie值,通常會採用split()的方法將cookie值中的名/值對都分離出來。
把cookie的值從cookie屬性分離出來以後,必需要採用相應的解碼方式(取決於以前存儲cookie值時的採用的編碼方式),把值還原出來。好比,先採用decodeURIComponent()方法把cookie的值解碼出來,以後再利用JSON.parse()方法轉換成json對象。
下面的例子定義了一個getcookie()函數,該函數將document.cookie屬性的值解析出來,將對應的名/值存儲到一個對象中,函數最後返回該對象。
/**解析document.cookie屬性的值**/ //將document.cookie的值以名/值對組成一個對象返回 //假設存儲cookie的值的時候是採用encodeURIComponent()編碼的 function getcookie() { var cookie = {}; //初始化要返回的對象 var all = document.cookie; //在一個大寫的字符串中獲取全部的cookie值 if (all === "") //若是cookie爲空字符串 return cookie; //返回一個空對象 var list = all.split(";"); //分離出名/值對 for (var i = 0; i < list.length; i++) { //遍歷每一個cookie var cookie = list[i]; var p = cookie.indexOf("="); //查找第一個"="符號 var name = cookie.substring(0, p); //獲取cookie名字 var value = cookie.substring(p + 1); //獲取cookie對應的值 value = decodeURIComponent(value); //對其值進行解碼 cookie[name] = value; //將名/值對存儲到對象中 } return cookie; }
在wamp下測試,不能用,結果都會直接等於list而不是對象。cookie不能直接用啦,修改以下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <script type="text/javascript"> function setcookie(name, value, daysTolive) { var cookie = name + "=" + encodeURIComponent(value); if (typeof daysTolive === "number") cookie += "; max-age =" + (daysTolive * 60 * 60 * 24); document.cookie = cookie; } setcookie("cook","cool",60); function getcookie() { var cookie = {}; //初始化要返回的對象 var all = document.cookie; //在一個大寫的字符串中獲取全部的cookie值 if (all === "") //若是cookie爲空字符串 return cookie; //返回一個空對象 var list = all.split(";"); //分離出名/值對 for (var i = 0; i < list.length; i++) { //遍歷每一個cookie var cookieEle = list[i]; var p = cookieEle.indexOf("="); //查找第一個"="符號 var name = cookieEle.substring(0, p); //獲取cookie名字 var value = cookieEle.substring(p + 1); //獲取cookie對應的值 value = decodeURIComponent(value); //對其值進行解碼 cookie[name] = value; //將名/值對存儲到對象中 } return cookie; } console.log(getcookie()); </script> </body> </html>
cookie的設計初衷是給服務端腳本用來存儲少許的數據的,該數據會在每次請求一個相關的URL時傳遞到服務器中。RFC2965鼓勵瀏覽器供應商對cookie的數據大小不作限制。但是,要知道,該標準不容許瀏覽器保存超過300個cookie,爲每一個web服務器保存的cookie數不能超過20個(是對整個服務器而言,而不只僅指服務器上的頁面和站點),並且,每一個cookie保存的數據不能超過4k。實際上,現代瀏覽器容許cookie總數超過300個,可是部分瀏覽器對單個cookie大小仍然有4k的限制。
例:定義一個cookieStorage函數,經過將max-age和path屬性傳遞給該構造函數,經過將max-age和path屬性傳遞給該構造函數,就會返回一個對象,而後就能夠像使用localStorage屬性或sessionStorage同樣來使用這個對象。可是要注意的是,該例並無實現存儲事件,所以,當設置和查詢cookieStorage對象的屬性的時候,不會實現自動保存和獲取對應的值。
實現基於cookie的API。
IE以及IE5以上的瀏覽器是經過在document元素後附件一個專屬的"DHTML行爲"來實現客戶端存儲的。以下代碼所示:
var memory = document.createElement("div"); //建立一個元素 memory.id = "_memory"; memory.style.display = "none"; memory.style.behavior = "url('default#userData')"; //附加userData行爲 document.body.appendChild(memory); //添加到document元素中
一旦元素賦予了"userData"行爲,該元素就擁有load()和save()方法。load()方法用於載入存儲的數據。使用它的時候必須傳遞一個字符串做爲參數--相似一個文件名,該參數用來指定要載入的存儲數據。當數據載入後,就能夠經過該元素的屬性來訪問這些名/值對形式的數據,可使用gettAttribute()來查詢攝像數據。經過setAttribute()方法設置屬性。而後調用save()方法能夠存儲新的數據;而要刪除數據,經過使用removeAttribute()方法而後調用save()方法便可。以下所示(該例使用了此前例子中初始化的那個memory元素):
memory.load("mySoredData"); //根據指定名,載入對於的數據 var name = memory.getAttribute("username"); //獲取其中數據片斷 if (!name) { //若是沒有指定的數據片斷 name = prompt("請輸入"); // memory.setAttribute("username", name); //將其設置成memory元素的一個屬性 memory.save("mySoredData") }
默認狀況下,經過userData存儲的數據,除非手動去刪除它不然永不失效。可是,也能夠經過設置expires屬性來指定它的過時時間。就拿上面的例子來講,能夠給存儲的數據設置時長爲100天的有效期,以下所示:
var now = (new.Date()).getTime(); //獲取當前時間,以毫秒爲單位 var expires = now + 100 * 24 * 60 * 60 * 1000; //100天的毫秒算法 expires = new Date(expires).toUTCString(); //將其轉換爲字符串。 memory.expires = expires; //設置userData的過時時間
IE userData的做用域限制在和當前文檔同目錄的文檔中。它的做用域沒有cookie寬泛,cookie對其所在目錄下的子目錄也有效。userData的機制並無像cookie那樣,經過設置path和domain屬性來控制或改變其做用域的方式。
userData容許存儲的數據量要比cookie大,可是卻比localStorage和sessionStorage容許的存儲量的數據量要小。
下面的例子基於IE的userData實現存儲了API提供的getItem(),setItem()以及removeItem()方法(可是它沒有實現key()或者clear()方法,緣由是userData並無定義遍歷全部存儲項的一種方法)。
。。。。。。
因爲上述代碼只在IE瀏覽器下有效,最好使用IE條件註釋來避免其餘瀏覽器載入上述代碼。
<!--[if IE]> <script src="userDataStorage.js"></script> <![endif]-->
HTML5中新增了「應用程序緩存」,容許web應用程序自身本地保存到用戶的瀏覽器中。不像localStorage和sessionStorage只是保存web應用程序相關的數據,它是將應用程序自身保存起來----應用程序所需運行的全部文件(HTML、CSS、JavaScript、圖片等)。「應用程序緩存」和通常的瀏覽器緩存不一樣:它不會隨着用戶清除瀏覽器緩存而被清除。同時,緩存起來的應用程序也不會像通常固定大小的緩存那樣,老數據會被最近一次訪問的新數據代替掉。它其實不是臨時存儲在緩存中:應用程序更像是被「安裝」在那裏,除非被用戶「卸載」或「刪除」它們,不然,它們就會一直「駐紮」在那裏。因此說,「應用程序緩存」在真正意義上不是「緩存」更好的說法應該稱之爲「應用程序存儲」。
讓web應用可以實現「本地安裝」的目的是要保證它們可以在離線狀態(好比,當在飛機或者手機沒信號的時候)下依然可訪問。將本身「安裝」到應用程序緩存中的Web應用,在離線狀態下使用localStorage來保存應用相關的數據,同時還具有一套同步機制,在再次回到在線狀態的時候,可以將存儲的數據傳輸給服務器。
想要將應用程序「安裝」到應用程序緩存中,首先要建立一個清單:包含全部應用程序依賴的全部url列表。而後,經過在應用程序主HTML頁面的<html>標籤中設置manifest屬性,指向到清單文件就能夠了:
<!DOCTYPE HTML> <html manifest=」myapp.appcache」> <head>…</head> <body>…</body> </html>
清單文件中的首行內容必須以」CACHE MANIFEST」字符串開始。其他就是要緩存的文件URL列表,一行一個URL。相對路徑的URL都相對於清單文件的URL 。會忽略內容中的空行,會做爲註釋而忽略以」#」開始的行。註釋前面能夠有空格,但同在同一行註釋後面是不容許有非空字符串的。
好比:
CACHE MANIFEST
#上面一行標識此文件是一個清單文件。本行是註釋
# 下面的內容都是應用程序依賴的資源文件的URL
myapp.html
myapp.js
myapp.css
images/background.png
補充:
緩存清單的MIME類型:
應用程序緩存清單文件約定以.appcache做爲文件擴展名。可是,這也僅僅只是約定而已,web服務器真正識別清單文件的方式是經過」text/cache-manifest」這個MIME類型的一個清單。若是服務器將清單文件的Content-Type的頭信息設置成其餘MIME類型,那麼就不會緩存應用程序了。所以,可能須要對web服務器作必定的配置來使用這個MIME類型,好比,在Web應用目錄下建立Apache服務器的一個.htaccess文件
清單文件包含要緩存的應用的標識。若是一個Web應用有不少web頁面,那麼每一個html頁面就須要設置<html manifest=>屬性來指向清單文件。事實上,將這些不一樣的頁面都指向同一個清單文件,可能很清楚地表達出它們都是須要緩存起來的,同時它們又是來自同一個web應用的。若是一個應用只有少許的html頁面,那麼通常會把這些頁面都顯示地列在清單文件中。但這不是強調的,會認爲任何連接到清單文件的文件都是web應用的一部分,並會隨着應用一塊兒緩存起來。
像以前提到的,一個簡單的清單必須列出web應用依賴的全部資源。一旦一個Web應用首次下載下來並緩存,以後的任何加載請求都來自緩存。從緩存中去載入一個應用資源的時候,就要求它請求的資源務必要在清單中。不會載入不在清單的資源。這種政策有點離線的味道。若是一個簡單的緩存起來的應用可以從緩存中載入並運行,那麼它也能夠在瀏覽器的離線狀態下運行。一般狀況下,不少複雜的web應用沒法將它們依賴的全部資源都緩存起來。可是,若是它們同時也有一個複雜的清單的話,它們仍然可能使用應用程序緩存。
複雜的清單
清單文件還有比這更復雜的語法,列舉資源的方式也還有另外兩種。在清單文件中可使用特殊的區域頭(譯者注:相似於HTTP頭)來標識該頭信息以後清單項的類型。像該例中列舉的簡單緩存項事實上都屬於「CACHE:」區域,這也是默認的區域。另外兩種區域是以「Network:」和」FALLBACK:」 頭信息開始的(一個清單文件能夠有任意數量的區域,並且能夠相鄰兩個區域之間能夠根據須要相互切換)。
「NETWORK:」區域標識了該區域中的資源從不緩存,總要經過網絡獲取。一般,會將一些服務端的腳本資源放在」NETWORK:」區域中,而通常該區域中的資源的URL都只是URL前綴,用來表示以此URL前綴開頭的資源都應該要經過網絡加載。」NETWORK:」區域中的URL還支持」*」通配符。該通配符表示對任何不在清單中的資源,瀏覽器都將經過網絡去獲取。這實際上違背了這樣一條規則:緩存應用程序必需要在清單中列舉全部應用相關的資源!
「FALLBACK:」區域中的清單項每行都包含兩個URL。第二個URL是指須要緩存起來的資源,第一個URL是一個前綴。任何可以匹配到該前綴的資源都不會緩存起來,可是可能的話,他們會從網絡中載入。若是從網絡中載入失敗的話,會使用第二個URL指定的資源來代替,從緩存中獲取。想象一個應用包含了必定數量的視頻教程。這些視頻都很大,顯然把他們緩存到本地是不合適的。所以,在離線狀態下,經過清單文件中的fallback區域,就可使用一些文本類的幫助文檔來代替了。
示例
CACHE MANIFEST CACHE: myapp.html myapp.css myapp.js FALLBACK: videos/ offline_help.html NETWORK: cgi/
當一個web應用從緩存中載入的時候,全部與之相關的文件也是直接從緩存中獲取。在線狀態下,瀏覽器會異步檢查是否清單文件有更新。若是有更新,新的清單文件以及全部清單中列舉的文件都會下載下來從新保存到應用程序緩存中。可是,要注意的是,瀏覽器只是檢查清單文件,而不會去檢查緩存的文件是否有更新:只檢查清單文件。比方說,你修改了一個緩存的JavaScript文件,要想讓該文件生效,就必須去更新下清單文件。因爲應用程序依賴的文件列表其實並無變化,所以最簡單的方式就是更新版本號:
CACHE MANIFEST # MyApp version 1 (更改這個數字以便讓瀏覽器從新下載這個文件) MyApp.html MyApp.js
一樣的,若是想要讓web應用從緩存中「卸載」,要在服務器端刪除清單文件,使得請求該文件的時候返回HTTP 404 沒法找到 的錯誤,同時,修改HTML文件與該清單列表「斷開連接」。
要注意的是,瀏覽器檢查清單文件以及更新緩存的操做是異步的,多是在從緩存中載入應用以前,也有可能同時進行。所以,對於簡單的web應用而言,在你更新清單文件以後,用戶必須載入應用兩次才能保證最新的版本生效:第一次是從緩存中載入老版本隨後更新緩存,第二次才從緩存中載入最新的版本。
瀏覽器在更新緩存過程當中會觸發一系列事件,你能夠經過註冊處理程序來跟蹤這個過程同時提供反饋給用戶。
......
離線web應用指的是將本身「安裝」在應用程序緩存中的程序,使得哪怕在瀏覽器處於離線狀態時候依然可訪問。舉個最簡單的例子——相似時鐘和萬花筒生成器這樣的應用——這是web應用要離線可用須要作的事情。可是,大多數web用也須要向服務器上傳數據:哪怕是簡單的遊戲應用都有可能須要上傳用戶的最高得分到服務器。這類應用也能夠成爲離線應用。他們可使用localStorage來存儲應用數據,而後當在線的時候再將數據上傳到服務器。在本地存儲和服務器端同步數據是將Web應用轉變爲離線應用最巧妙的環節,特別是當用戶須要從多臺設備獲取數據的時候。
爲了在離線狀態可用,web應用須要能夠告知別人本身是離線仍是在線,同時當網絡鏈接的狀態發生改變時候也能「感知」到。經過navigator.onLine屬性,能夠檢測瀏覽器是否在線,同時,在Window對象上註冊在線和離線事件處理程序,能夠檢測網絡鏈接狀態的改變。
一個簡單的記事本程序
20170420補充
瀏覽器對於存儲數據的大小有限制,限制的大小廣泛在5M/域,超出則會報Uncaught QuotaExceededError錯誤。所以在開發時應注意控制存儲數據保持在限制大小內,並定時清除無用的數據。若要手動刪除數據,Chrome瀏覽器可至chrome://settings/cookies 查看不一樣網站已使用本地存儲的佔用空間狀況,並進行刪除操做。