標籤:style blog http color io os 使用 ar java
當我們在提及web前端本機存放區的時候,首先需要介紹一下本地化儲存的概念和曆史。本地化儲存從來不是一個新奇的概念,因為web應用程式一直在追求的就是媲美甚至超越傳統型應用程式。但是傳統型應用程式一直優於web應用程式一個很重要的原因是它的本地化儲存得到了很好的支援。對於本地應用程式,作業系統會提供一個抽象層,用於儲存和擷取特定於應用程式的資料,這些資料可以儲存於註冊表、INI檔案,或者其他什麼地方,這取決於作業系統的實現,如果本地應用程式需要不單是索引值對形式的本機存放區,可以使用嵌入式資料庫或其他很多種解決方案。而對於web應用程式,它的本機存放區一步一步走到今天的HTML5本機存放區是非常不容易的。為了描述它的曆史,我們可以先看一張圖片:
從圖片可以看出,無論是從儲存資料的大小還是相容性來看,web前端本機存放區都走得不容易。在著重介紹HTML5本機存放區之前,我們先來看一看前面幾個儲存方式的概念。
HTTP cookie:HTTP cookie的缺點很明顯,最多隻能儲存4KB的資料,每個HTTP請求都會被傳送回伺服器,明文傳輸(除非你使用SSL)。
IE userData:userData是微軟在上世紀90年代的瀏覽器大戰時推出的本機存放區方案,藉助DHTML的behaviour屬性來儲存本機資料, 允許每個頁面最多儲存64K資料,每個網站最多640K資料,userData的缺點顯而易見,它不是Web標準的一部分,除非你的程式只需要支援IE, 否則它基本沒什麼用處。
Flash cookie:Flash cookie的名字有些誤導,它實際上和HTTP cookie並不是一回事,或許它的名字應該叫做"Flash本機存放區”,Flash cookie預設允許每個網站儲存不超過100K的資料,如果超出了,Flash會自動向使用者請求更大的儲存空間,藉助Flash的 ExternalInterface介面,你可以很輕鬆地通過Javascript操作Flash的本機存放區。Flash的問題很簡單,就是因為它是 Flash。
Google Gears:Gears是Google在07年發布的一個開源瀏覽器外掛程式,旨在改進各大瀏覽器的相容性,Gears內建了一個基於SQLite的嵌入式 SQL資料庫,並提供了統一API對資料庫進行訪問,在取得使用者授權之後,每個網站可以在SQL資料庫中儲存不限大小的資料,Gears的問題就是 Google自己都已經不用它了。
從上面的簡介我們可以看出,在以前,本機存放區面臨的主要問題是,對於儲存容量較大的方式,需要特定的外掛程式支援;對於不需要外掛程式支援的儲存方式,則處於安全問題或者大小限制而遭到扼殺。在這種雙重的矛盾面前,HTML5本機存放區橫空出世,對於前端開發人員是一種巨大的福音。
所謂的HTML5本機存放區更精確的說法應該是DOM儲存。根據MDN的定義,DOM儲存的機制是通過儲存字串類型的鍵/值對,來提供一種安全的存取方式.這個附加功能的目標是提供一個全面的,可以用來建立互動式應用程式的方法(包括那些進階功能,例如可以離線工作一段時間)。
HTML5的DOM儲存分成兩種:SessionStorage和LocalStorage。在當代瀏覽器中的相容性如下:
中提及的globalStorage是非標準的,已經廢棄,在這裡我們直接忽略它。而sessionStorage和localStorage在絕大部分現代瀏覽器中已經得到了很好的支援,但是既然是絕大部分,就必須照顧那些還不支援這兩個對象的瀏覽器。為了檢測瀏覽器是否支援這兩個對象,我們可以簡單的用下面的代碼來檢測:
1 function storageSupport() { 2 try { 3 return ‘localStorage‘ in window && window[‘localStorage‘] !== null; 4 } catch (e) { 5 return false; 6 } 7 }
非常幸運的是,這兩種對象的使用方式都非常簡單,這裡借用網上 的一張圖:
首先我們來看一看sessionStorage,sessionStorage 是個全域對象,它維護著在頁面會話(page session)期間有效儲存空間。只要瀏覽器開著,頁面會話周期就會一直持續。當頁面重新載入(reload)或者被恢複(restores)時,頁面會話也是一直存在的。每在新標籤或者新視窗中開啟一個新頁面,都會初始化一個新的會話。這句話看起來比較抽象,我們直接看一個demo:
1 var name = sessionStorage.setItem("myname","yuanzm");2 alert(sessionStorage.getItem("myname"));
當我們在瀏覽器中開啟的時候,就會快顯視窗,顯示“yuanzm”,然後我們按F12鍵,查看瀏覽器的調試視窗:
我們能夠發現,在瀏覽器的本機存放區sessionStorage中已經有了key值為“myname”的項。這個時候,重新整理頁面,仍然會彈出“yuanzm”,因為如果不調用sessionStorage.removeItem()或者手動清除這個項的話,這個項將一直存在。而上面提到的“只要瀏覽器開著,頁面會話周期就會一直持續。當頁面重新載入(reload)或者被恢複(restores)時,頁面會話也是一直存在的。每在新標籤或者新視窗中開啟一個新頁面,都會初始化一個新的會話”的意思是說,如果我們不重新設定myname的值,在新開啟一個瀏覽器標籤或者再次開啟一個瀏覽器視窗的時候,這個值是不存在的,也就是null。為了驗證這一點,很簡單,我們把上面兩行代碼的第一行注釋掉,然後重新整理頁面,接著在新的瀏覽器標籤中開啟這個檔案。這兩個動作分別會產生什麼效果呢?答案很簡單,當再次重新整理頁面的時候,仍然會彈出“yuanzm”,因為這個資料已經儲存在本地了,而修改代碼之後在新的頁面開啟,得到的結果是null,因為當前頁面會話中沒有“myname”這個值。
接下來我們看一看localStorage,他是跨多個視窗,且持續範圍可超過當前會話;意味著當瀏覽器關閉再重新開啟,資料依然是可用的;拿上面的例子來說,當修改代碼之後,在新的標籤開啟頁面,仍然會彈出“yuanzm”,我們再次在瀏覽器中查看效果:
由於這兩個對象的使用很簡單,暫時就介紹到這裡。下面還需要介紹一下的就是相容性問題。原因很簡單,因為並不是所有的瀏覽器都支援這兩個對象。這裡的相容包括兩種,第一種是在沒有原生支援localStorage的瀏覽器中使用,第二種是相容不同瀏覽器對於這兩種用法的差異。對於第一種,MDN給出了相容代碼:
if (!window.localStorage) { Object.defineProperty(window, "localStorage", new (function () { var aKeys = [], oStorage = {}; Object.defineProperty(oStorage, "getItem", { value: function (sKey) { return sKey ? this[sKey] : null; }, writable: false, configurable: false, enumerable: false }); Object.defineProperty(oStorage, "key", { value: function (nKeyId) { return aKeys[nKeyId]; }, writable: false, configurable: false, enumerable: false }); Object.defineProperty(oStorage, "setItem", { value: function (sKey, sValue) { if(!sKey) { return; } document.cookie = escape(sKey) + "=" + escape(sValue) + "; path=/"; }, writable: false, configurable: false, enumerable: false }); Object.defineProperty(oStorage, "length", { get: function () { return aKeys.length; }, configurable: false, enumerable: false }); Object.defineProperty(oStorage, "removeItem", { value: function (sKey) { if(!sKey) { return; } var sExpDate = new Date(); sExpDate.setDate(sExpDate.getDate() - 1); document.cookie = escape(sKey) + "=; expires=" + sExpDate.toGMTString() + "; path=/"; }, writable: false, configurable: false, enumerable: false }); this.get = function () { var iThisIndx; for (var sKey in oStorage) { iThisIndx = aKeys.indexOf(sKey); if (iThisIndx === -1) { oStorage.setItem(sKey, oStorage[sKey]); } else { aKeys.splice(iThisIndx, 1); } delete oStorage[sKey]; } for (aKeys; aKeys.length > 0; aKeys.splice(0, 1)) { oStorage.removeItem(aKeys[0]); } for (var iCouple, iKey, iCouplId = 0, aCouples = document.cookie.split(/\s*;\s*/); iCouplId < aCouples.length; iCouplId++) { iCouple = aCouples[iCouplId].split(/\s*=\s*/); if (iCouple.length > 1) { oStorage[iKey = unescape(iCouple[0])] = unescape(iCouple[1]); aKeys.push(iKey); } } return oStorage; }; this.configurable = false; this.enumerable = true; })());}View Code
至於第二種,在github上面有很多優秀的代碼,博主這裡推薦其中一份:github localStorage
最後,歡迎轉載原文,但是希望加上轉載連結:http://www.cnblogs.com/yuanzm/p/4023295.html
web前端實現本機存放區