一:概述
在前端开发中,经常要用到浏览器存储,浏览器存储有如下作用:
- 可有效减少前后端交互;
- 可以实现跨页面传值;
二:浏览器端存储方案
按F12进入控制面板的application中,可以看到浏览器存储的项目,如下图:
1.cookie
cookie 是服务器保存在浏览器的一小段文本信息。浏览器每次向服务器发出请求,就会自动附上这段信息。有些开发者使用 它作为客户端储存,这样做可行,但并不推荐,因为 cookie 的设计目标并不是这个,它的容量太小,每个 Cookie 的大小一般不能超过4KB,这个容量用于数据存储就太小气了。
保存位置:
- 若未设置过期时间,则保存在
内存
中,浏览器关闭后销毁 - 若设置了过期时间,则保存在
系统硬盘
中,直到过期时间结束后才消失(即使关闭浏览器)
【浏览器每次向服务器发出请求,就会自动附上这段信息】,这句话其实不是绝对的,如果用户禁用了cookie功能(在浏览器的设置面板里可以禁用的),那么浏览器就可以即不接收服务器设置的cookie,同时发送给服务器的请求也不会携带cookie。
通过window.navigator.cookieEnabled可以判断浏览器是否禁用了cookie功能,它的值是一个布尔值,只读。(true:表示浏览器启用了cookie功能;false:表示浏览器禁用了cookie功能)。
不同浏览器对 Cookie 数量和大小的限制,是不一样的。一般来说,单个域名设置的 Cookie 不应超过30个,每个 Cookie 的大小不能超过4KB。超过限制以后,Cookie 将被忽略,不会被设置。
浏览器的同源政策规定,两个网址只要【域名】相同和【端口】相同,就可以共享 Cookie。注意,这里不要求协议相同。也就是说,http://example.com
设置的 Cookie,可以被https://example.com
读取。
cookie并不一定非要服务器端生成,其实浏览器端同样能够生成,生成写入的信息介绍如下:
- cookie 的名字(例:age)
- cookie 的值(例:26)
- expires:到期时间(值是 UTC 格式)。(例:Thu,01-Jan-2020 00:00:08 GMT)
- max-age:指从现在开始 Cookie 存在的时间(单位:秒)。(例:300)功能类似于expires
- domain:所属域名(默认是当前域名)
- path:生效的路径(默认是当前网址)
最主要的设置就是前4项了,所属域名和生效路径一般就用默认的。
此外,设置max-age比设置expires更好,因为浏览器的时间是可以被更改的,不够可靠。
【读取】cookie方法:document.cookie;
- document.cookie会返回当前域名下的所有cookie(有个前提:该 Cookie 不能有
HTTPOnly
属性。)
【写入】cookie方法:document.cookie="name=张三;expires=Thu,01-Jan-2020 00:00:08 GMT"
- 未设置的属性按默认的处理
- 写入的时候,Cookie 值必须写成
key=value
的形式。注意,等号两边不能有空格。 - 写入 Cookie 时若有分号、逗号和空格进行转义(它们都不允许作为 Cookie 的值)。
-
document.cookie
一次只能写入一个 Cookie。
【删除】cookie方法:删除一个现存 Cookie 的唯一方法,是设置它的expires
属性为一个过去的日期。
- document.cookie="name=张三;expires=Thu,01-Jan-1990 00:00:08 GMT"
缺点:
- 安全性差(因为每次前端发送请求都会带上cookie);
- 浪费带宽(也是因为每次前端发送请求都会带上cookie);
- 数据操作不方便,原生接口不友好,需要自己封装;
应用场景
- 判断用户是否登陆过网站,以便下次登录时能够实现自动登录(或者记住密码)
- 保存登录时间、浏览次数等信息
问题:既然cookie不适合做浏览器端的大量数据存储,那么一旦有这种需求,怎么办哪?
答:使用 Web storage和 IndexedDB。
2.sessionStorage 和 localStorage
storage
接口用于脚本在浏览器保存数据。有两个对象部署了这个接口:window.sessionStorage
和window.localStorage
。
sessionStorage
保存的数据用于浏览器的一次会话,当会话结束(通常是窗口关闭),数据被清空;
localStorage
保存的数据若不主动清空,则一直存在;
除了保存期限的长短不同,这两个对象的其他方面都一致。
storage
接口很像 cookie 的强化版,能够使用大得多的存储空间。目前,每个域名的存储上限视浏览器而定,详见如下:
--Chrome: 2.5MB;
--Firefox:5MB;
--Opera:5MB;
--IE:10MB。
storage
接口提供了1个属性,5个方法。
1个属性:length
--window.sessionStorage.length;
--window.localStorage.length;
5个方法:
--setItem(key, value);【写入】
--getItem(key, value);【读取】
--removeItem(key); 【删除指定的key名的storage】
--clear(); 【删除所有的storage】
--key(一个整数); 【返回参数对应的键名】
说明:除了key()方法,其它方法的参数都是字符串类型。
cookie 和 webStorage 存储数据格式仅支持 String,存储时需要借助 JSON.stringify()
将 JSON 对象转化为字符串,读取时需要借助 JSON.parse()
将字符串转化为 JSON 对象。
webStorage
有许多优点:
- 保存在客户端,不与服务器通信,因此比
cookie
更安全、速度更快 - 存储空间有限,但比 cookie 大(5MB)
- 仅支持
String
类型的存储内容(和 cookie 一样) - html5 提供了原生接口,数据操作比 cookie 方便
问题:一般来说,我们更推荐使用 webStroage,但其存储大小有限、数据存储仅支持 String 格式、不提供搜索功能,不能建立自定义的索引,有没有更好的方案?
答: IndexedDB
可以担任该重任。
3.indexedDB
通俗地说,IndexedDB 就是浏览器提供的本地数据库,它可以被网页脚本创建和操作。IndexedDB 允许储存大量数据,提供查找接口,还能建立索引。这些都是 LocalStorage 所不具备的。
从 DB(Data Base) 可以看出它是一个数据库。常用的数据库有两种类型:
- 关系型数据库:数据存储在表中,使用 sql 语句操作数据库,如:
MySQL
、Oracle
、WebSQL
(已废弃) - 非关系型数据库:数据集作为 JSON 对象存储,不需要写sql 语句,如:
Redis
、MongoDB
、IndexedDB
IndexedDB 是非关系型数据库,不需要写 sql 语句进行数据库操作,数据格式可使用 JSON 对象。
4.WebSQL(已废弃)
三:适用场景
- cookie:短期登陆,例如:token 会过期,需要设置过期时间,过期后重新换取 token;
- sessionStorage:敏感账号一次性登录、浏览器窗口关闭后数据被销毁;
- localStorage:长期登录、判断用户是否已登录,适合长期保存在本地的数据;
- indexedDB:存储大量结构化数据数据(但是由于前端安全问题,将大量结构化数据存在前端还是难以推行,对于大量结构化数据目前还是采用存后端比较常见)
四:总结
我们经常会听到有个session,这是个什么鬼,跟sessionStorage、cookie等有什么关系?
答:没有半毛钱关系。
session:
- 是后端关心的内容,依赖于 cookie(sessionID 保存在cookie中)
- 保存在服务端内存
- 存储大小无限制
- 支持任何类型的存储内容
cookie
存储量小、安全性差、数据操作接口不友好;
webStorage
存储量较大、安全性较高、数据接口友好;
若要持久的存储方式,推荐使用 localStorage
若要一次性会话的存储,推荐使用 sessionStorage
indexDB推广并不理想。