Web Storage API

隨著Web應用程序出現,產生了能夠直接在C端存儲用戶信息能力的要求。想法也合乎邏輯,屬于某個特定用戶的信息應該存在該用戶的機器上。無論是登陸信息、偏好設定或其他數據。
這個問題的第一個方案是以cookie的形式出現的,cookie原來是網景公司創造的。

使用 Web Storage API

Cookie

HTTP Cookie,通常直接叫做cookie,最初是在用戶端用于存儲會話信息的。該標準要求服務器對任意HTTP請求發送Set-Cookie HTTP頭作為響應的一部分。其中包含會話信息。例如,這種服務器響應的頭可能如下:

    HTTP/1.1 200 OK
    Content-type: text/html
    Set-Cookie: name=value
    Other-header: other-header-value

這個HTTP響應設置以name為名稱、以value為值的一個cookie,鍵值在傳送時都必須是URL編碼的。瀏覽器會存儲這樣的會話信息,并在這之后,通過為每個請求添加Cookie HTTP頭將信息發送服務器,如下:

    GET /index.html HTTP/1.1
    Cookie: name=value
    Other-header: other-header-value

發送回服務器的額外信息可以用于驗證客戶來自于發送的哪個請求。


Cookie的限制
cookie在性質上時綁定在特定的域名下的。當設定了一個cookie后,再給創建它的域名發送請求時,都會包含這個cookie。這個限制確保了存儲在cookie中的信息只能讓批準的接受者訪問,而無法被其他域訪問。
關鍵詞:綁定在特定的域下

由于cookie時存在客戶端計算機上的,還加入了一些限制確保cookie不會被惡意使用,同時不會占據太多磁盤空間。每個域的cookie總數是有限的。

  • IE6以及更低版本限制每個域名20個cookie。
  • IE7每個域50個。
  • Firefox限制每個域50個。
  • Opera限制每個域最多30個。
  • Safari和Chrome對于每個域的cookie數量沒有限制(???)

當超過上限后繼續設置cookie,瀏覽器就會清除以前設置的cookie。
瀏覽器對cookie的大小也有限制,大多數瀏覽器都有大約4096B(+-1)的長度限制。為了最佳的瀏覽器兼容,最好將整個cookie長度限制在4095B以內。
如果嘗試創建超過最大尺寸限制的cookie,那么該cookie會悄無聲息的地丟掉。

cookie的構成

  • 名稱
    一個唯一確定cookie的名稱。cookie名稱是不區分大小寫的,所以myCookie和MyCookie被認為是同一個cookie。然而,實踐中最好區分大小寫。

  • 存儲在cookie中的字符串值,值必須被URL編碼。

  • cookie對于哪個域是有效的,所有向該域發送的請求中都會包含這個cookie信息。這個值可以包含子域,也可以不包含,如果不做規定,那個這個域會被認作來自設置cookie的那個域。
  • 路徑
    對于指定域中的那個路徑,應該向服務器發送cookie。
  • 失效時間
    表示cookie何時應該被刪除的時間戳(也就是何時應該停止向服務器發送這個cookie)。默認情況下瀏覽器會話結束時即將所有cookie刪除;不過也可以自己設置刪除時間。這個值是個GMT格式日期。因此cookie可在瀏覽器關閉后依然存在用戶機器上。如果你設置的失效日期是個以前的時間,則cookie會被立刻刪除。
  • 安全標志
    制定后,cookie只有在使用SSL連接的時候才發送到服務器。例如,cookie信息只能發送給https://www.wrox.com,而http://www.wrox.com的請求則不能發送cookie。
    每一段信息都作為Set-Cookie頭的一部分,使用分號加空格分隔每一段。
HTTP/1.1 200 OK
Content-type: text/html
Set-Cookie: name=value; expires=Mon, 22-Jan-07 07:10:24 GMT; domain=.wrox.com
Other-header: other-header-value

頭信息指定了一個名為name的cookie,它會在格林威治時間2007年1月22日7:10:24失效,同時對于www.wrox.comwrox.com的任何子域(如p2p.wrox.com)都有效。
secure標志是cookie中唯一一個非鍵值對的部分,直接包含一個secure單詞。如下:

HTTP/1.1 200 OK
Content-type: text/html
Set-Cookie: name=value; domain=.wrox.com; path=/; secure
Other-header: other-header-value

這里設置了secure標志,這個cookie只能通過SSL連接才能傳輸。

尤其要注意,域、路徑、失效時間和secure標志都是服務器給瀏覽器的指示,已指定何時應該發送cookoie。這些參數并不會作為發送服務器的cookie信息的一部分,只有鍵值對才會被發送。

JS中的cookie
在JS中處理cookie有些復雜,因為其中所周知的蹩腳的接口,即BOM的document.coookie屬性。這個屬性的獨特指出在于 它會因為使用它的方式不同表現出不同的行為。

當用來獲取屬性值時,document.cookie返回當前頁面可用的所有cookie的字符串,一系列由分號隔開的鍵值對。

name1=value1;name2=value2;name3=value3

所有名字和值都是URL編碼,所以必須使用docodeURLComponent()解碼。

當用于設置值的時候,document.cookie屬性可以設置為一個新的字符串,這個cookie字符串會被解釋并添加到現有cookie集合中,設置document.cookie并不會覆蓋cookie,除非設置的cookie已經存在。設置格式如下:

name=value; expires=expiration_time; path=domain_path; domain=domain_name; secure

這些參數中,只有cookie的名字和值是必需的。

document.cookie = "name=Nicholas";

這段代碼創建了一個名為name的cookie,值為Nicholas。當客戶端每次向服務器發送請求的時候,都會發送這個cookie;當瀏覽器關閉的時候,他就會被刪除。

由于JS中讀寫cookie不是很直觀,常常需要一些函數簡化cookie功能。基本的cookie操作有三種:讀取、寫入和刪除。他們在CookieUtil對象中如下:

        var CookieUtil = {
            get: function(name) {
                var cookieName = encodeURIComponent(name) + "=",
                    cookieStart = document.cookie.indexOf(cookieName),
                    cookieValue = null;
                
                if (cookieStart > 1) {
                    var cookieEnd = document.cookie.indexOf(";",cookieStart);
                    if (cookieEnd == -1) {
                        cookieEnd = document.cookie.length;
                    }
                    cookieValue = decodeURIComponent(document.coookie.substring(cookieStart + cookieName.length, cookieEnd));
                }

                return cookieValue;
            },
            set: function(name,value,expires,path,domain,secure) {
                var cookieText = encodeURIComponent(name) + "=" + encodeURIComponent(value);

                if (expires instanceof Date) {
                    cookieText += "; expires=" + expires.toGMTString();
                }
                if (path) {
                    cookieText += "; path=" + path;
                }
                if (domain) {
                    cookieText += "; domain=" + domain;
                }
                if (secure) {
                    cookieText += "; secure";
                }
                document.cookie = cookieText;
            },
            unset: function(name,path,domain,secure) {
                this.set(name, "", new Date(0), path, domain, secure);
            }
        };

CookieUtil.get()方法根據cookie的名字獲取相應的值。它會在document.cookie字符串中查找cookie名加上等于號的位置。找到了使用indexOf()查找該位置后的第一個分號(表示該cookoie結束位置)。如果沒有分號,表示該cookie時字符串最后一個,則余下的字符串都是cookie的值。該值使用decodeURLComponent()進行解碼并最后返回。如果沒有發現cookie,則返回null。

......
可以這樣使用上述方法:


        // 設置cookie
        CookieUtil.set("name","Nicholas");
        CookieUtil.set("book","Professional JavaScript");

        // 讀取cookie值
        console.log(CookieUtil.get("name"));    // "Nicholas"
        console.log(CookieUtil.get("book"));    // "Professional JavaScript"

        // delete cookie
        CookieUtil.unset("name");
        CookieUtil.unset("book");

        // 設置cookie,包括它的路徑、域、失效日期
        CookieUtil.set("name","Nicholas","/books/projs/","www.wrox.com",new Date("January 1, 2010"));

        // 刪除剛剛設置的cookie
        CookieUtil.unset("name","/books/projs/","www.wrox.com");

        // 設置安全的cookie
        CookieUtil.set("name","Nicholas",null,null,null,true);

Web Storage

Web Storage最早是在WHAT-WG的Web應用1.0規范描述的。目的是客服由cookie帶來的一些限制,當數據需要被嚴格控制在客戶端時,無須持續的將數據發回服務器。

  • 提供一種在cookie之外存儲會話數據的途徑;
  • 提供一種存儲大量可以跨會話存在的數據的機制。

最初的Web Storage規范包含了兩種對象定義:sesionStorage和globalStorage。

Stroage類型
Storage類型提供最大的存儲空間(因瀏覽器而異)來存儲鍵值對。

  • clear()
    刪除所有值;Firefox中沒有實現。

  • getItem(name)
    根據指定的名字name獲取對應的值。

  • key(index)
    獲取index位置處的值的名字

  • removeItem(name)
    刪除由name指定的鍵值對。

  • setItem(name,value)
    為指定的name設置一個對應的值。

Storage類型只能存儲字符串,非字符串的數據在存儲之前會被轉換成字符串

sessionStorage對象
sessionStorage對象存儲特定于某個會話的數據,也就是該數據只保持到瀏覽器關閉。這個對象就像cookie,也會在瀏覽器關閉后消失。sessionStorage中的數據可以跨越頁面刷新而存在,同時瀏覽器支持,瀏覽器崩潰后重啟依然可用。
因為sessionStorage中的數據綁定于某個服務器會話,當文件在本地運行時不可用。數據只能由最初給對象存儲數據的頁面訪問到。

//使用方法存儲數據
sessionStorage.setItem("name", "Nicholas");

// 使用屬性存儲數據
sessionStorage.book = "Professional JavaScript";

sessionStorage中有數據時,可以使用getItem()或者通過直接訪問屬性名來獲取數據。

// 使用方法讀取數據
var name = sessionStorage.getItem("name");

// 使用屬性讀取數據
var book = sessionStorage.book;

還可以通過結合length屬性和key()方法來迭代值。

        for (var i = 0, len = sessionStorage.length; i < len; i++) {
            var key = sessionStorage.key(i);
            var value = sessionStorage.getItem(key);
            console.log(key + "=" + value);
        }

sessionStorage對象應該主要用于僅針對會話的小段數據的存儲。如果需要跨越會話存儲數據,那么globalStorage或者localStorage更合適。

localStorage對象

要訪問同一個localStorage對象,頁面必須來自用一個域名,使用同一種協議,在同一個端口上。
由于localStorage時Storage的實例,所以可以像使用sessionStorage一樣使用它。

localStorage.setItem("name","Nicholas");
localStorage.book = "Professional JavaScript";
var name localStorage.getItem("name");
var book = localStorage.book;

存儲在localStorage中的數據和存儲在globalStorage中的數據一樣,都遵循同樣規則,數據保留到通過JS刪除或者用戶清除瀏覽器緩存。

storage事件

對Storage對象做任何修改,都會在文檔上觸發storage事件,當通過屬性或setItem()方法保存數據,使用delete操作符或removeItem()刪除數據,調用clear()方法時,都會發生該事件。這個事件event對象有以下屬性。

  • domain:發生變化的存儲空間的域名
  • key:設置或者刪除的鍵名
  • newValue:如果設置新值,則是新值;如果刪除,則是null。
  • oldValue:鍵被更改之前的值。

限制
與其他客戶端數據存儲方案類似,web storage同樣也有限制。大多數桌面瀏覽器會設置每個來源5MB的限制,chrome和safari對每個來源限制2.5MB。而IOS版safari和Android版webkit的限制也是2.5MB。
對sessionStorage的限制也是因瀏覽器而異。有的瀏覽器對sessionStorage的大小沒有限制。有關限制參考

參考:

詳說 Cookie, LocalStorage 與 SessionStorage
cookie、localStorage和sessionStorage 三者之間的區別以及存儲、獲取、刪除等使用方式
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • ??支持離線 Web 應用開發是 HTML5 的另一個重點。 ??所謂離線 Web 應用,就是在設備不能上網的情況...
    霜天曉閱讀 1,077評論 0 2
  • Web Storage和cookie的區別cookie只能設置大約4kb的數據,Web Storage可以保存高達...
    IT小C閱讀 598評論 0 9
  • 其實這是很簡單的一個API。但這個API也存在不少問題可以深究一下。 說到這個API,我就想起曾經一次面試:當時面...
    丘云閱讀 932評論 0 0
  • 第一部分 HTML&CSS整理答案 1. 什么是HTML5? 答:HTML5是最新的HTML標準。 注意:講述HT...
    kismetajun閱讀 27,646評論 1 45
  • 本文是我今年2月份發表在博客園上的文章,平常做項目時便溫故一下。私以為,只有通過實踐才能將知識真正地內化和吸收,再...
    一個笑點低的妹紙閱讀 859評論 0 2