浏览器存储
概括
类型 | 大小 | 失效时间 | 说明 |
---|---|---|---|
Cookie | 4k | 可设置 | cookie 会被 HTTP 请求头携带 |
localStorage | 5m不一 | 永久有效 | 同源下共享 |
sessionStorage | 5m不一 | 当前会话有效 | 同源下不一定共享 |
差异
localStorage
在同一浏览器中不同窗口或者标签页中是共享的sessionStorage
有两种情况:- 只能存在同一浏览器下的同一窗口中,不同窗口或者标签页是不共享的
- 在同页面的两个同源的
iframe
页面是可以共享的
localStorage 是一个对象,即 typeof localStorage === 'object',所以对象的一些操作方法也是适用的 window 作为全局对象,使用时可以省略
Storage 的基本操作
除了原生的操作方法外,因为 Storage
是一个对象,所以对象的操作方法同样对其适用。
以 localStorage
为例:
- 存储
JS
window.localStorage.setItem('key', 'value') // 使用 setItem 方式最为直观
window.localStorage['key'] = 'value' // 以属性形式存储不直观,日常不要使用
window.localStorage.key = 'value'
window.localStorage.setItem('key', 'value') // 使用 setItem 方式最为直观
window.localStorage['key'] = 'value' // 以属性形式存储不直观,日常不要使用
window.localStorage.key = 'value'
- 读取
JS
window.localStorage.getItem('key')
window.localStorage.getItem('key')
- 删除
JS
window.localStorage.removeItem('key') // 使用 removeItem 方式最为直观
delete window.localStorage.key // 使用 delete 删除形式不直观,日常不要使用
delete window.localStorage['key']
window.localStorage.removeItem('key') // 使用 removeItem 方式最为直观
delete window.localStorage.key // 使用 delete 删除形式不直观,日常不要使用
delete window.localStorage['key']
- 清空
JS
window.localStorage.clear()
window.localStorage.clear()
- 获取存储条数
JS
window.localStorage.length // 当前存储数据条数,未想到使用场景
window.localStorage.length // 当前存储数据条数,未想到使用场景
获取所有存储 key 或 value 值
JS
Object.keys(window.localStorage) // 获取所有 key 值
Object.values(window.localStorage) // 获取所有 value 值
Object.keys(window.localStorage) // 获取所有 key 值
Object.values(window.localStorage) // 获取所有 value 值
- 是否存在某个属性
JS
if(localStorage.getItem('key') === null) {} // 一般方法
localStorage.hasOwnProperty('key') // 使用 obejct 的 hasOwnProperty 方法判断
if(localStorage.getItem('key') === null) {} // 一般方法
localStorage.hasOwnProperty('key') // 使用 obejct 的 hasOwnProperty 方法判断
JSON 序列化
WebStorage
只能存储字符串,对于引用类型数据,我们需要利用 JSON 序列化将其转为字符串进行存储。
JS
JSON.stringify(val)
JSON.stringify(val)
局限性:如 undefined
, Function
, Symbol
等类型会在序列化时丢失。
我们也经常会利用 JSON
系列化方式实现对象的深拷贝功能。
事件监听
WebStorage
在修改时会触发 storage
事件,该事件会对所有同源窗口生效,我们可以利用该特性做前端退出登录等可能存在多窗口业务。
注意:因为 sessionStorage
是无法跨标签页共享的,所以它不能通过 storage
事件监听,但被放在 iframe
页面中是可以的。
JS
window.addEventListener("storage", ({ url, key, oVal, nVal }) => {
//
})
window.addEventListener("storage", ({ url, key, oVal, nVal }) => {
//
})
存储容量检测
JS
// 要做判断,只支持 https 协议
if(navigator && navigator.storage) {
// 返回值是一个 promise
navigator.storage.estimate().then(estimate => {
// 返回值 estimate 是个对象,格式为 {quota: xxx, usage: xxx, usageDetails: { xxx }}
// 其中 quota 为容量, usage 是使用量,usageDetails 是 indexedDB 等使用量
console.log(estimate)
});
}
// 要做判断,只支持 https 协议
if(navigator && navigator.storage) {
// 返回值是一个 promise
navigator.storage.estimate().then(estimate => {
// 返回值 estimate 是个对象,格式为 {quota: xxx, usage: xxx, usageDetails: { xxx }}
// 其中 quota 为容量, usage 是使用量,usageDetails 是 indexedDB 等使用量
console.log(estimate)
});
}
存储溢出清理
当插入新内容时,如果内容过大可能会导致存储溢出,则 先检查存储容量是否够,不够则尝试删除掉一些不需要的数据,比如通过 keys 方法去查找有哪些缓存字段,也可以结合上面添加缓存失效时间的管理,移除已失效的缓存。
问题
1. WebStorage 不能设置过期时间,有什么解决方案呢?
我们可以在每次存储数据的时候,给其加上当前时间戳属性,获取的时候将这个时间戳与当然时间对比,如果大于过期时间,则将其删除。为了使用便捷性,我们可以将本地存储封装个方法同一管理。
不过,这种方式是有隐藏问题的,如果用户更改了操作系统时间,比如将时间调到了过期时间之后,将导致所有缓存失效。也就是说客户端的时间是不可信的。