Web Storage API

隨著Web應(yīng)用程序出現(xiàn)逞泄,產(chǎn)生了能夠直接在C端存儲用戶信息能力的要求铛漓。想法也合乎邏輯,屬于某個(gè)特定用戶的信息應(yīng)該存在該用戶的機(jī)器上士复。無論是登陸信息图谷、偏好設(shè)定或其他數(shù)據(jù)翩活。
這個(gè)問題的第一個(gè)方案是以cookie的形式出現(xiàn)的阱洪,cookie原來是網(wǎng)景公司創(chuàng)造的。

使用 Web Storage API

Cookie

HTTP Cookie菠镇,通常直接叫做cookie冗荸,最初是在用戶端用于存儲會話信息的。該標(biāo)準(zhǔn)要求服務(wù)器對任意HTTP請求發(fā)送Set-Cookie HTTP頭作為響應(yīng)的一部分利耍。其中包含會話信息蚌本。例如,這種服務(wù)器響應(yīng)的頭可能如下:

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

這個(gè)HTTP響應(yīng)設(shè)置以name為名稱隘梨、以value為值的一個(gè)cookie程癌,鍵值在傳送時(shí)都必須是URL編碼的。瀏覽器會存儲這樣的會話信息轴猎,并在這之后嵌莉,通過為每個(gè)請求添加Cookie HTTP頭將信息發(fā)送服務(wù)器,如下:

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

發(fā)送回服務(wù)器的額外信息可以用于驗(yàn)證客戶來自于發(fā)送的哪個(gè)請求捻脖。


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

由于cookie時(shí)存在客戶端計(jì)算機(jī)上的椎扬,還加入了一些限制確保cookie不會被惡意使用,同時(shí)不會占據(jù)太多磁盤空間具温。每個(gè)域的cookie總數(shù)是有限的蚕涤。

  • IE6以及更低版本限制每個(gè)域名20個(gè)cookie。
  • IE7每個(gè)域50個(gè)桂躏。
  • Firefox限制每個(gè)域50個(gè)钻趋。
  • Opera限制每個(gè)域最多30個(gè)。
  • Safari和Chrome對于每個(gè)域的cookie數(shù)量沒有限制(剂习?蛮位?较沪?)

當(dāng)超過上限后繼續(xù)設(shè)置cookie,瀏覽器就會清除以前設(shè)置的cookie失仁。
瀏覽器對cookie的大小也有限制尸曼,大多數(shù)瀏覽器都有大約4096B(+-1)的長度限制。為了最佳的瀏覽器兼容萄焦,最好將整個(gè)cookie長度限制在4095B以內(nèi)控轿。
如果嘗試創(chuàng)建超過最大尺寸限制的cookie,那么該cookie會悄無聲息的地丟掉拂封。

cookie的構(gòu)成

  • 名稱
    一個(gè)唯一確定cookie的名稱茬射。cookie名稱是不區(qū)分大小寫的,所以myCookie和MyCookie被認(rèn)為是同一個(gè)cookie冒签。然而在抛,實(shí)踐中最好區(qū)分大小寫。

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

  • cookie對于哪個(gè)域是有效的,所有向該域發(fā)送的請求中都會包含這個(gè)cookie信息票唆。這個(gè)值可以包含子域朴读,也可以不包含,如果不做規(guī)定走趋,那個(gè)這個(gè)域會被認(rèn)作來自設(shè)置cookie的那個(gè)域衅金。
  • 路徑
    對于指定域中的那個(gè)路徑,應(yīng)該向服務(wù)器發(fā)送cookie吆视。
  • 失效時(shí)間
    表示cookie何時(shí)應(yīng)該被刪除的時(shí)間戳(也就是何時(shí)應(yīng)該停止向服務(wù)器發(fā)送這個(gè)cookie)典挑。默認(rèn)情況下瀏覽器會話結(jié)束時(shí)即將所有cookie刪除;不過也可以自己設(shè)置刪除時(shí)間啦吧。這個(gè)值是個(gè)GMT格式日期您觉。因此cookie可在瀏覽器關(guān)閉后依然存在用戶機(jī)器上。如果你設(shè)置的失效日期是個(gè)以前的時(shí)間授滓,則cookie會被立刻刪除琳水。
  • 安全標(biāo)志
    制定后,cookie只有在使用SSL連接的時(shí)候才發(fā)送到服務(wù)器般堆。例如在孝,cookie信息只能發(fā)送給https://www.wrox.com,而http://www.wrox.com的請求則不能發(fā)送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

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

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

這里設(shè)置了secure標(biāo)志五辽,這個(gè)cookie只能通過SSL連接才能傳輸。

尤其要注意外恕,域杆逗、路徑、失效時(shí)間和secure標(biāo)志都是服務(wù)器給瀏覽器的指示鳞疲,已指定何時(shí)應(yīng)該發(fā)送cookoie罪郊。這些參數(shù)并不會作為發(fā)送服務(wù)器的cookie信息的一部分,只有鍵值對才會被發(fā)送建丧。

JS中的cookie
在JS中處理cookie有些復(fù)雜排龄,因?yàn)槠渲兴苤孽磕_的接口,即BOM的document.coookie屬性翎朱。這個(gè)屬性的獨(dú)特指出在于 它會因?yàn)槭褂盟姆绞讲煌憩F(xiàn)出不同的行為。

當(dāng)用來獲取屬性值時(shí)尺铣,document.cookie返回當(dāng)前頁面可用的所有cookie的字符串拴曲,一系列由分號隔開的鍵值對。

name1=value1;name2=value2;name3=value3

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

當(dāng)用于設(shè)置值的時(shí)候,document.cookie屬性可以設(shè)置為一個(gè)新的字符串店溢,這個(gè)cookie字符串會被解釋并添加到現(xiàn)有cookie集合中叁熔,設(shè)置document.cookie并不會覆蓋cookie,除非設(shè)置的cookie已經(jīng)存在床牧。設(shè)置格式如下:

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

這些參數(shù)中荣回,只有cookie的名字和值是必需的。

document.cookie = "name=Nicholas";

這段代碼創(chuàng)建了一個(gè)名為name的cookie戈咳,值為Nicholas心软。當(dāng)客戶端每次向服務(wù)器發(fā)送請求的時(shí)候,都會發(fā)送這個(gè)cookie著蛙;當(dāng)瀏覽器關(guān)閉的時(shí)候删铃,他就會被刪除。

由于JS中讀寫cookie不是很直觀踏堡,常常需要一些函數(shù)簡化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()方法根據(jù)cookie的名字獲取相應(yīng)的值缎患。它會在document.cookie字符串中查找cookie名加上等于號的位置。找到了使用indexOf()查找該位置后的第一個(gè)分號(表示該cookoie結(jié)束位置)阎肝。如果沒有分號挤渔,表示該cookie時(shí)字符串最后一個(gè),則余下的字符串都是cookie的值风题。該值使用decodeURLComponent()進(jìn)行解碼并最后返回判导。如果沒有發(fā)現(xiàn)cookie,則返回null沛硅。

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


        // 設(shè)置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");

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

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

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

Web Storage

Web Storage最早是在WHAT-WG的Web應(yīng)用1.0規(guī)范描述的摇肌。目的是客服由cookie帶來的一些限制擂红,當(dāng)數(shù)據(jù)需要被嚴(yán)格控制在客戶端時(shí),無須持續(xù)的將數(shù)據(jù)發(fā)回服務(wù)器围小。

  • 提供一種在cookie之外存儲會話數(shù)據(jù)的途徑昵骤;
  • 提供一種存儲大量可以跨會話存在的數(shù)據(jù)的機(jī)制。

最初的Web Storage規(guī)范包含了兩種對象定義:sesionStorage和globalStorage肯适。

Stroage類型
Storage類型提供最大的存儲空間(因?yàn)g覽器而異)來存儲鍵值對变秦。

  • clear()
    刪除所有值;Firefox中沒有實(shí)現(xiàn)框舔。

  • getItem(name)
    根據(jù)指定的名字name獲取對應(yīng)的值蹦玫。

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

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

  • setItem(name,value)
    為指定的name設(shè)置一個(gè)對應(yīng)的值刘绣。

Storage類型只能存儲字符串樱溉,非字符串的數(shù)據(jù)在存儲之前會被轉(zhuǎn)換成字符串

sessionStorage對象
sessionStorage對象存儲特定于某個(gè)會話的數(shù)據(jù),也就是該數(shù)據(jù)只保持到瀏覽器關(guān)閉纬凤。這個(gè)對象就像cookie福贞,也會在瀏覽器關(guān)閉后消失。sessionStorage中的數(shù)據(jù)可以跨越頁面刷新而存在移斩,同時(shí)瀏覽器支持肚医,瀏覽器崩潰后重啟依然可用。
因?yàn)閟essionStorage中的數(shù)據(jù)綁定于某個(gè)服務(wù)器會話向瓷,當(dāng)文件在本地運(yùn)行時(shí)不可用肠套。數(shù)據(jù)只能由最初給對象存儲數(shù)據(jù)的頁面訪問到。

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

// 使用屬性存儲數(shù)據(jù)
sessionStorage.book = "Professional JavaScript";

sessionStorage中有數(shù)據(jù)時(shí)猖任,可以使用getItem()或者通過直接訪問屬性名來獲取數(shù)據(jù)你稚。

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

// 使用屬性讀取數(shù)據(jù)
var book = sessionStorage.book;

還可以通過結(jié)合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對象應(yīng)該主要用于僅針對會話的小段數(shù)據(jù)的存儲。如果需要跨越會話存儲數(shù)據(jù)刁赖,那么globalStorage或者localStorage更合適搁痛。

localStorage對象

要訪問同一個(gè)localStorage對象,頁面必須來自用一個(gè)域名宇弛,使用同一種協(xié)議鸡典,在同一個(gè)端口上。
由于localStorage時(shí)Storage的實(shí)例枪芒,所以可以像使用sessionStorage一樣使用它彻况。

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

存儲在localStorage中的數(shù)據(jù)和存儲在globalStorage中的數(shù)據(jù)一樣,都遵循同樣規(guī)則舅踪,數(shù)據(jù)保留到通過JS刪除或者用戶清除瀏覽器緩存纽甘。

storage事件

對Storage對象做任何修改,都會在文檔上觸發(fā)storage事件抽碌,當(dāng)通過屬性或setItem()方法保存數(shù)據(jù)悍赢,使用delete操作符或removeItem()刪除數(shù)據(jù),調(diào)用clear()方法時(shí)货徙,都會發(fā)生該事件左权。這個(gè)事件event對象有以下屬性。

  • domain:發(fā)生變化的存儲空間的域名
  • key:設(shè)置或者刪除的鍵名
  • newValue:如果設(shè)置新值破婆,則是新值涮总;如果刪除,則是null祷舀。
  • oldValue:鍵被更改之前的值。

限制
與其他客戶端數(shù)據(jù)存儲方案類似烹笔,web storage同樣也有限制裳扯。大多數(shù)桌面瀏覽器會設(shè)置每個(gè)來源5MB的限制,chrome和safari對每個(gè)來源限制2.5MB谤职。而IOS版safari和Android版webkit的限制也是2.5MB饰豺。
對sessionStorage的限制也是因?yàn)g覽器而異。有的瀏覽器對sessionStorage的大小沒有限制允蜈。有關(guān)限制參考

參考:

詳說 Cookie, LocalStorage 與 SessionStorage
cookie冤吨、localStorage和sessionStorage 三者之間的區(qū)別以及存儲、獲取饶套、刪除等使用方式
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末漩蟆,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子妓蛮,更是在濱河造成了極大的恐慌怠李,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異捺癞,居然都是意外死亡夷蚊,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進(jìn)店門髓介,熙熙樓的掌柜王于貴愁眉苦臉地迎上來惕鼓,“玉大人,你說我怎么就攤上這事唐础∠淦纾” “怎么了?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵彻犁,是天一觀的道長叫胁。 經(jīng)常有香客問我,道長汞幢,這世上最難降的妖魔是什么驼鹅? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮森篷,結(jié)果婚禮上输钩,老公的妹妹穿的比我還像新娘。我一直安慰自己仲智,他們只是感情好买乃,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著钓辆,像睡著了一般剪验。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上前联,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天功戚,我揣著相機(jī)與錄音,去河邊找鬼似嗤。 笑死啸臀,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的烁落。 我是一名探鬼主播乘粒,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼伤塌!你這毒婦竟也來了灯萍?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤寸谜,失蹤者是張志新(化名)和其女友劉穎竟稳,沒想到半個(gè)月后属桦,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡他爸,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年聂宾,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片诊笤。...
    茶點(diǎn)故事閱讀 39,696評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡系谐,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出讨跟,到底是詐尸還是另有隱情纪他,我是刑警寧澤,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布晾匠,位于F島的核電站茶袒,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏凉馆。R本人自食惡果不足惜薪寓,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望澜共。 院中可真熱鬧向叉,春花似錦、人聲如沸嗦董。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽京革。三九已至奇唤,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間匹摇,已是汗流浹背冻记。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留来惧,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓演顾,卻偏偏與公主長得像供搀,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子钠至,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評論 2 353

推薦閱讀更多精彩內(nèi)容

  • ??支持離線 Web 應(yīng)用開發(fā)是 HTML5 的另一個(gè)重點(diǎn)棉钧。 ??所謂離線 Web 應(yīng)用屿脐,就是在設(shè)備不能上網(wǎng)的情況...
    霜天曉閱讀 1,033評論 0 2
  • Web Storage和cookie的區(qū)別cookie只能設(shè)置大約4kb的數(shù)據(jù),Web Storage可以保存高達(dá)...
    IT小C閱讀 586評論 0 9
  • 其實(shí)這是很簡單的一個(gè)API。但這個(gè)API也存在不少問題可以深究一下的诵。 說到這個(gè)API万栅,我就想起曾經(jīng)一次面試:當(dāng)時(shí)面...
    丘云閱讀 920評論 0 0
  • 第一部分 HTML&CSS整理答案 1. 什么是HTML5? 答:HTML5是最新的HTML標(biāo)準(zhǔn)西疤。 注意:講述HT...
    kismetajun閱讀 27,474評論 1 45
  • 本文是我今年2月份發(fā)表在博客園上的文章烦粒,平常做項(xiàng)目時(shí)便溫故一下。私以為代赁,只有通過實(shí)踐才能將知識真正地內(nèi)化和吸收扰她,再...