Web 客户端存储

2,182 阅读5分钟
原文链接: blog.percymong.com
许可协议: 知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议

开门见山,先来总结一下 Cookie, LocalStorageSessionStorage 的异同,精华都在这儿呢!

总结异同

  • 相同点

    • 三者都是键值对的集合
    • 三者都会在浏览器端保存,数据存储有大小限制,同源策略限制
  • 不同点

    • 主要用途不同: cookie 主要用于标识用户身份,而 Web Storage 主要用于浏览器端存储数据
    • 操作频率不同: 一般情况下浏览器端不会修改 cookie,但会频繁操作 Web Storage
    • 存储容量不同: cookie 最大允许存储 4KB,而 Web Storage 每一个源支持 5MB(这个视浏览器而定,最小保守是 5MB,并且各浏览器支持的 localStorage 和 sessionStorage 容量上限不同。)
    • 是否添加到HTTP请求: cookie 每次都会包含在 http 请求中,而 Web Storage 由脚本控制选择性提交
    • 有效期不同: cookie 在设置的有效期内都有效,sessionStorage 在当前页面关闭前有效,localStorage 长期有效,直到 用户删除它或通过脚本删除它
    • 不同页面是否允许共享: sessionStorage 不能共享,localStorage 在同源文档之间共享, cookie 在同源且符合 path 规则的文档之间共享
    • 是否拥有专用 API: Web API 中没有专门操作 cookie 的 API,localStorage 和 sessionStorage 共用一套 API(Storage 对象的API)

基本概念

  • Cookie 是一种存储在用户电脑上的用来记录一些有状态性的信息的小数据。
    • 记录购物车中添加的商品ID
    • 记录用户上网习惯,比如最近浏览了哪些页面
    • 记录用户的身份验证信息(比如账号密码)

An HTTP cookie wiki (also called web cookie, Internet cookie, browser cookie or simply cookie) is a small piece of data sent from a website and stored on the user’s computer by the user’s web browser while the user is browsing.

  • cookie 的缺陷
    • Cookie会被附加在每个HTTP请求中,所以无形中增加了流量。
    • 由于在HTTP请求中的Cookie是明文传递的,所以安全性成问题。(除非用HTTPS)
    • Cookie的大小限制在4KB左右。对于复杂的存储需求来说是不够用的。

基本用法

  • document.cookie:获取或设置与当前文档相关联的cookie。

  • 使用 navigator.cookieEnabled 检测当前页面是否启用了 cookie

if (!navigator.cookieEnabled) { 
  alert('Please enable cookie~');
}
  • 一个 cookie 是一个键值对形式的字符串(name=value)
// 添加一个 cookie
document.cookie = 'author=percy';

cookie的值的字符串不允许包含任何逗号、分号或空格,所以可以用 encodeURIComponent() 来保证它不包含任何逗号、分号或空格。

let value = 'hello;w,orld;';
document.cookie = 'greet=' + encodeURIComponent(value);
  • 使用 document.cookie 一次只能写入或更新一个 cookie
假设现在 document.cookie 是一个空字符串
document.cookie = 'name=p'; // right
document.cookie; // "name=p"
document.cookie = 'name=percy;age=21'; // not good
document.cookie; // "name=percy"
  • 还可以为 cookie 添加一些以下的可选属性
// 设置 cookie 所在的路径
var path = '/';
// 设置 cookie 所在的域名
var domain = 'blog.percymong.com';
 //设置有效期,60*30 就是半小时有效,60*60*24*365 就是一年有效
var max-age = 60*30;
// 设置 cookie 的过期时间,这个值得格式是一个 UTC-time 字符串
var expires = (new Date()).toUTCString(); 
document.cookie = 'author=percy' +
                  ';path=' + path +         // 设置路径
                  ';domain=' + domain +     // 设置域名
                  ';max-age=' + max-age +   // 设置有效时间
                  ';expires=' + expires +   // 设置过期时间
                  ';secure';                // cookie只通过 https 协议传输

cookie 的作用域是通过文档源和文档路径来确定的,也可通过 cookie 的 path 和 domain 属性来配置不同的作用域。

当前页面: http://blog.percymong.com/2016/12/23/npm-summary/index.html
当前页面下,cookie 默认的 domain 和 path 如下:
domain: 'blog.percymong.com'
path: '/2016/12/23/npm-summary/'

通过修改 domain,可以满足一些特殊的业务需要:比如我现在需要在 blog.percymong.com 页面访问 www.percymong.com 页面下的 cookie

StackOverflow : How do browser cookie domains work?

注意,这里的 domain 是 '.percymong.com'。
document.cookie = 'author=percy;domain=.percymong.com';

cookie 有 path 概念,子路径可以访问父路径 cookie,父路径不能访问子路径 cookie。

当前页面: http://www.example.com/tag/index.html
假设在当前页面下设置了一个 cookie
该 cookie 对下面的页面是可见的:
http://www.example.com/tag/demo.html
http://www.example.com/tag/javascript/index.html
http://www.example.com/tag/css/test/demo.html
该 cookie 对下面的页面是不可见的:
http://www.example.com
http://www.example.com/index.html
http://www.example.com/test/demo.html

不同于 localStorage 和 sessionStorage,Web API 中没有专门用于操作 cookie 的 API,所以网上找到了别人写的一个库,专门操作 cookie。

库名:js.cookie.js,a simple, lightweight JavaScript API for handling browser cookies.

Web 存储(Web Storage)

Web Storage 包含两种机制:localStoragesessionStorage

  • window.localStorage:返回一个 Storage 对象
    • 存储在 localStorage 里面的数据没有过期时间,长期有效,直到用户主动删除它或通过脚本删除它
    • localStorage 的作用域仅限定在同源。
  • window.sessionStorage:也返回一个 Storage 对象
    • 存储在 sessionStorage 里面的数据在页面会话结束时(关闭当前页面或关闭浏览器)会被清除。页面会话在浏览器打开期间一直保持,并且重新加载或恢复页面仍会保持原来的页面会话。
    • 复制后的标签页不会保持原来的会话,但是会复制原页面的 sessionStorage 数据。(Chrome 亲测)
    • sessionStorage 的作用域不仅限定在同源,还限定在相同会话窗口中。

localStorage 和 sessionStorage 共用一套操作 API:Storage 对象 API

  • Storage 对象 API

    • Storage.length:返回存储的数据项数量
    • Storage.key(keyIndex):取得对应索引的键名
    • Storage.getItem(keyName):取得对应键名的值
    • Storage.setItem(keyName,keyValue):增加或更新一个数据项
    • Storage.removeItem(keyName):删除对应键名的数据项
    • Storage.clear():清空所有存储的数据项
  • storage 事件

对 Storage 对象进行任何修改,都会触发 storage 事件。

自己可以做个测试,打开同源的两个页面,一个页面修改 localStorage 数据,一个页面监听 storage 事件。

window.onstorage = function(e){
  console.log('key : ' + e.key); // 发生变化的键名
  console.log('oldValue : ' + e.oldValue);   // 旧值
  console.log('newValue : ' + e.newValue); // 新值
};

测试 sessionStorage 时,会有点小麻烦,看下面解释。

The sessionStorage is isolated for each tab, so they can not communicate. Events for sessionStorage are triggered only in between frames on the same tab.

参考资料


本文对你有帮助?欢迎扫码加入前端学习小组微信群: