前端需要了解的 Cookies 和 WebStorage
Cookies 和 WebStorage
為什么需要客戶端存儲(chǔ)
- 記錄用戶登錄狀態(tài),當(dāng)用戶下次訪問時(shí)不必重新登錄
- 存儲(chǔ)一些用戶對(duì)應(yīng)用的自定義偏好設(shè)置,例如主題色、表格每頁(yè)默認(rèn)顯示條數(shù)等
- 一些廣告商需要通過客戶端端存儲(chǔ)的一些用戶行為數(shù)據(jù)來做一些更個(gè)性化的推薦
恰當(dāng)?shù)睦每蛻舳舜鎯?chǔ)可以很好的優(yōu)化用戶體驗(yàn)
Cookies
Cookies 是什么
Cookies 其實(shí)就是網(wǎng)站存儲(chǔ)在客戶端的一些數(shù)據(jù)
這些數(shù)據(jù)會(huì)自動(dòng)的被加到網(wǎng)站發(fā)起的每個(gè) HTTP 請(qǐng)求的 Request Header 中
通常情況下服務(wù)端和客戶端都可以對(duì) Cookies 進(jìn)行 CRUD 操作
點(diǎn)這里查看 Cookies 協(xié)議
如何在前端新增 Cookie
// 最簡(jiǎn)單的設(shè)置方式 屬性全部采用默認(rèn)值 document.cookie = 'name=value' // 自定義 Cookie 屬性 document.cookie = 'test=111; max-age=3600; domain=xx.com; path=/;' 復(fù)制代碼注意一次只能同時(shí)新增一個(gè) Cookie
如何在前端修改或刪除 Cookie
// 修改 test 為 222 document.cookie = 'test=222; max-age=7200; domain=xx.com; path=/' // 刪除 test document.cookie = 'test=; max-age=0; domain=xx.com; path=/' 復(fù)制代碼這里要注意的是要確保 domain 以及 path 與待修改 Cookie 設(shè)置的一致
因?yàn)?Cookie 其實(shí)是在同一個(gè)域名和路徑下唯一
例如我們?cè)L問 www.a.com/test/xx.html
可以同時(shí)存在 test=1; domain=a.com; path=/test 以及 test=1; domain=a.com; path=/
這倆個(gè) name 相同但是 path 不同的同名 Cookie
所以只有 name domain path 這三個(gè)值都相同時(shí)才能確定一個(gè) Cookie
如何讀取 Cookie
通過 document.cookie 獲取到的是所有數(shù)據(jù)
類似 name1=value1; name2=value2 的字符串
要拿來使用的話還需通過一系列字符串操作將需要的值取出
如何判斷 Cookie 是否啟用
由于 Cookie 涉及到用戶的隱私,用戶可以手動(dòng)禁止瀏覽器使用 Cookie
絕大多數(shù)瀏覽器都可以通過以下代碼來判斷用戶是否禁用 Cookie
Ps: 經(jīng)本人測(cè)試 禁用 Cookie 后 Github 淘寶 等都無法正常訪問
感覺現(xiàn)在大多數(shù)用戶都不會(huì)去禁用 Cookie,不然會(huì)有一堆網(wǎng)站訪問不了
關(guān)于 Cookie 的屬性
- domain
指定 Cookie 存儲(chǔ)在哪個(gè)域名下 默認(rèn)為當(dāng)前服務(wù)器的域名
當(dāng)然也遵循同源策略 例如在 www.son.a.com 頁(yè)面下
我們可以設(shè)置 Cookie 的 domain 為 a.com
這樣在 www.another.a.com 頁(yè)面也可以獲取到該 Cookie
但是不能在該頁(yè)面試圖去操作 domain 為 b.com 的 Cookie - path
指定 Cookie 存儲(chǔ)在哪個(gè)路徑下 默認(rèn)為當(dāng)前 URI 中的路徑
例如在 www.a.com/page/one.html 我們按默認(rèn)屬性設(shè)置了一個(gè)Cookie
那么在 www.a.com/page/two.html www.a.com/page/son/three.html
這些頁(yè)面下都可以獲取這個(gè) Cookie
但是在 www.a.com/another/four.html 頁(yè)面上便無法得到這個(gè) Cookie
可以將 path 設(shè)為 / 使得訪問當(dāng)前域名下所有路徑的網(wǎng)頁(yè)都能拿到設(shè)置的 Cookie - max-age 最大存儲(chǔ)時(shí)間 以秒為單位 默認(rèn)當(dāng)瀏覽器 Session 結(jié)束時(shí)清除
- expires 存儲(chǔ)失效的 GMT 時(shí)間 默認(rèn)當(dāng)瀏覽器 Session 結(jié)束時(shí)清除
- secure 包含該屬性的 Cookie 只能通過 HTTPS 傳輸
- httponly
只能在服務(wù)端進(jìn)行設(shè)置
包含該屬性的 Cookie 只會(huì)在 Request Headers 中出現(xiàn)
前端無法通過 document.cookie 查看修改
關(guān)于 Cookie 中的保留字符
由于 ; , 空格 在 Cookie 中有特殊含義
所以當(dāng)存儲(chǔ)的數(shù)據(jù)中包含這些特殊字符時(shí)
需要在存儲(chǔ)前通過 encodeURIComponent 進(jìn)行編碼
讀取前通過 decodeURIComponent 進(jìn)行解碼
Cookie 的優(yōu)缺點(diǎn)
優(yōu)點(diǎn):
- 適合用于存放需要每個(gè)請(qǐng)求都必須攜帶的數(shù)據(jù)
- 服務(wù)端也可以直接操作 Cookie
- 可以通過 domain 以及 path 控制數(shù)據(jù)存儲(chǔ)的范圍
缺點(diǎn):
- 容量有限,規(guī)范只要求每個(gè)域名下最低提供 4kb 的存儲(chǔ)空間
- 每次請(qǐng)求都會(huì)攜帶,如果存放了大量不必要的數(shù)據(jù)很顯然會(huì)影響頁(yè)面性能
- 不安全,永遠(yuǎn)不要在 Cookie 中存放用戶的敏感數(shù)據(jù)
- 前端 API 不友好,CRUD 都是通過 document.cookie 進(jìn)行,沒有提供相關(guān)操作的方法
WebStorage
WebStorage 是什么
WebStorage 是 HTML5 新增的客戶端存儲(chǔ)機(jī)制
分為 LocalStorage 以及 SessionStorage
IE8+ 以及各現(xiàn)代瀏覽器對(duì)其都有良好的支持
點(diǎn)這里查看 WebStorage 規(guī)范
LocalStorage
永久存儲(chǔ)(除非瀏覽器緩存被清除)在當(dāng)前域下,遵循同源策略
如果在一個(gè)瀏覽器打開多個(gè)窗口訪問同一域名的網(wǎng)站
那么這多個(gè)窗口中的 LocalStorage 是共享的
SessionStorage
存儲(chǔ)周期為當(dāng)前 Session ,同樣遵循同源策略
要注意這里的 Session 和 Cookie 的默認(rèn)存儲(chǔ) Session 不同
SessionStorage 針對(duì)的是瀏覽器的每個(gè)窗口,而不是整個(gè)瀏覽器的進(jìn)程
正因如此,與 LocalStorage 不同的是,多個(gè)窗口下的同域名網(wǎng)站,其 SessionStorage 也是分開存儲(chǔ)的
Ps:要注意的是如果在一個(gè)窗口內(nèi)訪問的網(wǎng)站通過 <iframe> 內(nèi)嵌了倆個(gè)同域名網(wǎng)站
那么這倆個(gè) <iframe> 內(nèi)嵌站點(diǎn)的 SessionStorage 是共享的
API
// sessionStorage 與 localStorage 一致 localStorage.a = 'test1' // 新增或修改 localStorage.a // 讀取 localStorage['a'] // 讀取localStorage.setItem(a, 'test3') // 新增 localStorage.getItem(a) // 讀取 localStorage.removeItem(a) // 刪除 localStorage.clear() // 清空所有 localStorage.key(index) // 獲取指定 index 存儲(chǔ)鍵值對(duì)的 key localStorage.length // 總共存儲(chǔ)的鍵值對(duì)數(shù)量 復(fù)制代碼可以看到通過類似操作普通對(duì)象一樣來操作 WebStorage
通常來說這種方式更為簡(jiǎn)潔
但是也有類似 clear() removeItem() 等操作只能通過 API 進(jìn)行
Storage Event
WebStorage 還提供了事件機(jī)制,用于監(jiān)聽存儲(chǔ)發(fā)生的變化
當(dāng)打開倆個(gè)窗口訪問同域網(wǎng)站,如果在其中一個(gè)窗口中修改了存儲(chǔ)數(shù)據(jù)
在另一個(gè)窗口中可以通過如下代碼監(jiān)聽到存儲(chǔ)改變的事件
要注意的是這個(gè)事件只有在本地存儲(chǔ)真的發(fā)生變化時(shí)才會(huì)觸發(fā)
也就是說假設(shè)已經(jīng)通過 localStorage.a = 'test' 設(shè)置了本地存儲(chǔ)中 a 的值為 test
那么再次執(zhí)行 localStorage.a = 'test' 并不會(huì)觸發(fā)事件
并且通過 localStorage.removeItem('notExist') 試圖移除一個(gè)不存在的屬性時(shí)也不會(huì)觸發(fā)事件
Ps:(由于 SessionStorage 是基于瀏覽器窗口存儲(chǔ),所以只有當(dāng)使用 <iframe> 處理內(nèi)嵌頁(yè)面時(shí)才可能會(huì)觸發(fā)事件)
這個(gè)機(jī)制可以用于實(shí)現(xiàn)應(yīng)用的廣播功能,當(dāng)用戶在一個(gè)窗口的頁(yè)面進(jìn)行操作時(shí)同步對(duì)另一個(gè)窗口的頁(yè)面做出修改
例如用戶在一個(gè)窗口中修改了應(yīng)用的主題色,我們通過 localStorage.color = 'red' 來保存這一改變
另一個(gè)窗口通過監(jiān)聽到 localStorage 的變化同步的將應(yīng)用的主題色也修改為 red
WebStorage 的優(yōu)勢(shì)
- 每個(gè)域下允許存儲(chǔ)超過 5MB 的數(shù)據(jù)(各個(gè)瀏覽器有所不同)
- 更友好的 API
其它注意事項(xiàng)
- 不管是 Cookies 還是 WebStorage 都是與瀏覽器相關(guān)的
也就意味著在 Chrome 瀏覽器中存儲(chǔ)的數(shù)據(jù),當(dāng)用戶切換為 FireFox 瀏覽時(shí)就無法獲取
當(dāng)然這應(yīng)該是小概率事件,畢竟大多數(shù)人習(xí)慣于使用同一種瀏覽器 - 當(dāng)瀏覽器設(shè)置 Cookie 失敗時(shí)并不會(huì)報(bào)錯(cuò),這個(gè)過程是靜默的
例如當(dāng)你試圖跨域的去設(shè)置 Cookie 時(shí)只會(huì)發(fā)現(xiàn)不生效,但不會(huì)在控制臺(tái)中看到相應(yīng)錯(cuò)誤信息 - 雖然 WebStorage 的規(guī)范希望能支持對(duì)類似數(shù)組對(duì)象等結(jié)構(gòu)化數(shù)據(jù)進(jìn)行存儲(chǔ)
但目前為止大多數(shù)瀏覽器僅支持字符串作為 Value
傳入非字符串的值會(huì)被強(qiáng)制轉(zhuǎn)化為字符串
例如試圖通過 localStorage.o = {a: 1} 存儲(chǔ)一個(gè)對(duì)象
會(huì)發(fā)現(xiàn)實(shí)際存儲(chǔ)的是 o: "[object Object]"
(End)
總結(jié)
以上是生活随笔為你收集整理的前端需要了解的 Cookies 和 WebStorage的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: re:Invent解读:没想到你是这样的
- 下一篇: 2019年如何打造自己的“前端品牌”