為什麼要存資料到客戶端? 儲存資料在客戶端可以解決很多的問題和減少不必要的傳輸資料:
1. 能保存程式的狀態:使用者關閉瀏覽器再開啟後能知道他工作到哪了。
2. 能快取資料:許多不會變化的資料根本沒必要每次都從服務端取得。
3. 能保存使用者的喜好:這種資料通常不需要存在服務端。
以前的做法 在HTML5本地儲存之前,如果我們想在客戶端保存持久化數據,有這麼多選擇:
1. HTTP cookie。 HTTP cookie的缺點很明顯,最多只能儲存4KB的數據,每個HTTP請求都會傳送回伺服器,明文傳輸(除非你使用SSL)。
2. IE userData。 userData是微軟在90年代的瀏覽器大戰時推出的本地存儲方案,借助DHTML的behaviour屬性來存儲本地數據, 允許每個頁面最多存儲64K數據,每個站點最多640K數據,userData的缺點顯而易見,它不是Web標準的一部分,除非你的程式只需要支援IE, 否則它基本上沒什麼用處。
3. Flash cookie。 Flash cookie實際上和HTTP cookie並不是一回事,或許它的名字應該叫做"Flash本地存儲”,Flash cookie默認允許每個站點存儲不超過100K的數據,如果超出了,Flash會自動向用戶請求更大的儲存空間,借助Flash的ExternalInterface接口,你可以很輕鬆地透過Javascript操作Flash的本機儲存。 Flash的問題很簡單,就是因為它是 Flash。
4. Google Gears。 Gears是Google在07年發布的一個開源瀏覽器插件,旨在改進各大瀏覽器的兼容性,Gears內置了一個基於SQLite的嵌入式SQL數據庫,並提供了統一API對數據庫進行訪問,在獲取用戶授權之後,每個網站可以在SQL資料庫中儲存不限大小的數據,Gears的問題就是Google自己都已經不用它了。
眼花撩亂的各種技術所導致的就是瀏覽器的兼容性問題。這裡大家用的最多的可能就是cookie了。
HTML5中的全新體驗 針對以上的問題,HTML5中給出了更理想的解決方案:假如你需要儲存的只是簡單的用key/value對即可解決的數據,則可以使用Web Storage。
與Cookie相比,Web Storage存在不少的優勢,概括為以下幾點:
1. 儲存空間更大:IE8下每個獨立的儲存空間為10M,其他瀏覽器實作略有不同,但都比Cookie大很多。
2. 儲存內容不會發送到伺服器:當設定了Cookie後,Cookie的內容會隨著請求一併發送的伺服器,這對於本地儲存的資料是一種頻寬浪費。而Web Storage中的資料則只是存在本地,不會與伺服器發生任何互動。
3. 更多豐富易用的接口:Web Storage提供了一套更為豐富的接口,使得資料操作更為簡便。
4. 獨立的儲存空間:每個域(包括子域)都有獨立的儲存空間,且各個儲存空間是完全獨立的,因此不會造成資料混亂。
Web Storage分類 Web Storage其實由兩部分組成:sessionStorage與localStorage。
sessionStorage用於本地存儲一個會話(session)中的數據,這些數據只有在同一個會話中的頁面才能訪問並且當會話結束後數據也隨之銷毀。因此sessionStorage不是持久的本機存儲,只是會話層級的儲存。
localStorage用於持久化的本地存儲,除非主動刪除數據,否則數據是永遠不會過期的。
檢查是否支援Web Storage Web Storage在各大主流瀏覽器中都支援了,但是為了相容於老的瀏覽器,還是要檢查一下是否可以使用這項技術。
第一種方式:透過檢查Storage物件是否存在來檢查瀏覽器是否支援Web Storage:
複製程式碼
代碼如下: if(typeof(Storage)!=="undefined"){ // Yes! localStorage and sessionStorage support! // Some code... ..
} else {
// Sorry! No web storage support..
}
複製程式碼程式碼如下:
if (typeof(localStorage) == 'undefined' ) { alert('Your browser does not support HTML5 localStorage. Try upgrading.'); } else { Yes! localStorage and sessionStorage support! // Some code..... } 或: if('localStorage' in window && window['localStorage'] !== null) { // Yes! localStorage and sessionStorage support! // Some code..... } else { alert('Your browser does not support HTML5 localStorage. Try upgrading' ; } 或 if (!!localStorage) { // Yes! localStorage and sessionStorage support! // Some code..... } else {support! // Some code..... } else {support! 🎜>alert('Your browser does not support HTML5 localStorage. Try upgrading.'); }
很明顯第一個方式最直接,也最簡單。
Web Storage的使用
Web Storage中儲存的是鍵值對,而且瀏覽器會以字串方式儲存。記住在必要的時候將他們轉為其他格式。
sessionStorage與localStorage除了用途不同外,成員列表是一樣的:
代碼如下:
key = value: 存貯鍵值對 setItem(key, value): 存貯鍵值對 getItem(key): 取鍵值對 removeItem(key ):移除所有鍵值對 clear():清空所有鍵值對 length:鍵值對的數目
這裡還是要強調一下:setItem(key,value )方法中的value類型,理論上可以是任意類型,不過實際上瀏覽器會呼叫value的toString方法來取得其字串值並儲存到本機,因此如果是自訂的類型則需要自己定義有意義的toString方法。例如下面的例子結合JSON.stringify使用:
代碼如下:
var person = {'name': 'rainman', 'age': 24}; localStorage.setItem("me", JSON.stringify(person)); JSON.parse(localStorage.getItem( 'me')).name; // 'rainman' /** * JSON.stringify,將JSON資料轉換成字串 * JSON.stringify({'name': 'fred', 'age': 24}); // '{"name":"fred ","age":24}' * JSON.stringify(['a', 'b', 'c']); // '["a","b","c"]' * JSON.parse,反解JSON.stringify * JSON.parse('["a","b","c"]') // ["a","b","c" ] */
此外,添加鍵值對的時候,如果添加的數量比較多,比較保險的做法是去檢查是否有超出限額的異常:
代碼如下:
try { localStorage.setItem(itemId, values.join(';')); } catch (e) { if (e == QUOTA_EXCEEDED_ERR) { alert(>alert(>alert(>alert( 'Quota exceeded!'); } }
Web Storage的方法非常簡單,下面的範例是統計button點擊的次數的:
程式碼如下:
<script> <br />function clickCounter() <br />{ <br />if(typeof(Storage)!=="undefined") <br />{ <br />if (localStorage.clickcount) <br />{ <br />localStorage.clickcount=Number(localStorage.clickcount) 1; <br />} <br />else <br />{ <br />localStorage.clickcount=1; <br />} <br />document.Elementage.cIdcount=1; <br />} <br />document.Elementy" ).innerHTML="You have clicked the button " localStorage.clickcount " time(s)."; <br />} <br />else <br />{ <br />document.getElementById("result").inHTML="Sorryinner , your browser does not support web storage..."; <br />} <br />} <br /></script>
="clickCounter()" type="button">Click me!
Click the button to see the counter increase.
Close the browser tab (or window), and try again, and the counter will continue to count (is not reset).
在上面的範例中,你可以把localStorage換成sessionStorage,點擊幾次button然後驗證在關閉瀏覽器前後的效果。 存在的問題 Web Storage的缺陷主要集中在其安全性方面,具體體現在以下兩點: 1. 瀏覽器會為每個域分配獨立的存儲空間,也就是腳本在網域A中是無法存取到網域B中的儲存空間的,但是瀏覽器卻不會檢查腳本所在的網域與目前網域是否相同。即在域B中嵌入域A中的腳本依然可以存取域B中的資料。 2. 儲存在本地的資料未加密且永遠不會過期,極易造成隱私洩漏。 此外,更多的安全相關的問題請參考後面實用參考中的連結。 其他規範一覽(僅供了解,說不定什麼時候就沒了) Web Database 在老的HTML5提議中,假如你需要存儲複雜的數據則可以使用Web Database,可以像客戶端程式一樣使用SQL(Web Database標準已被廢棄,這裡就是簡單提一下);globalStorage 這個也是html5提出來,在瀏覽器關閉以後,使用globalStorage儲存的資訊仍能夠保留下來,localStorage一樣,網域中任何一個頁面儲存的資訊都能被所有的頁面共享, 不過目前只有FireFox支援。 基本語法: • globalStorage['developer.mozilla.org'] —— 在developer.mozilla.org下面所有的子域都可以透過這個命名空間儲存物件來進行讀取和寫入。 • globalStorage['mozilla.org'] —— 在mozilla.org網域下方的所有網頁都可以透過這個命名空間儲存物件來進行讀取和寫入。 • globalStorage['org'] —— 在.org網域下面的所有網頁都可以透過這個命名空間儲存物件來進行讀取和寫入。 • globalStorage[''] —— 在任何網域下的任何網頁都可以透過這個命名空間儲存物件來進行讀取和寫入 方法屬性: • setItem(key, value) —— 設定或重設key 值。 • getItem(key) —— 取得 key 值。 • removeItem(key) —— 刪除 key 值。 • 設定key 值:window.globalStorage["planabc.net"].key = value; • 取得key 值:value = window.globalStorage["planabc.net"].key; 其它它特徵: • 過期時間同localStorage,其它的一些特性也和localStorage相似。 • 現在Firefox只支援目前網域下的globalStorage存儲, 如果使用公用網域會導致一個這樣一個類似的錯誤「Security error」 code: “1000”。 IndexedDB 最後我們要介紹的就是IndexedDB了,相較於其他兩個規範,目前只有Firefox實作了IndexedDB(順便提一下,Mozilla表示它們永遠不會去實作Web SQL Database),不過Google已經表示正在考慮在Chrome中加入IndexDB支援。 IndexedDB引入了一個object store的概念,這有點像是一個SQL Database,你可以在“數據庫”中存儲“記錄”,並且每條“記錄”可以擁有很多“字段",每個字段都有一個特定的資料類型,你可以選擇記錄的子集, 並使用「遊標」進行遍歷,同時object store中的所有變更都是基於「事務」的。 更多的資訊參考後面使用參考中講述FireFox中IndexedDB的文件。 實用參考: 官方文件:http://www.w3schools.com/html5/ 腳本之家:http:// www.jb51.net/w3school/html5/ 本地儲存的安全性:http://www.mhtml5.com/2012/03/4586.html FireFox的實驗特性IndexedDB:https://developer.mozilla.org/en-US/docs/IndexedDB