Skip to content
本页目录

浏览器存储

概括

类型大小失效时间说明
Cookie4k可设置cookie 会被 HTTP 请求头携带
localStorage5m不一永久有效同源下共享
sessionStorage5m不一当前会话有效同源下不一定共享

差异

  • localStorage 在同一浏览器中不同窗口或者标签页中是共享的
  • sessionStorage 有两种情况:
    1. 只能存在同一浏览器下的同一窗口中,不同窗口或者标签页是不共享的
    2. 在同页面的两个同源的 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 不能设置过期时间,有什么解决方案呢?

我们可以在每次存储数据的时候,给其加上当前时间戳属性,获取的时候将这个时间戳与当然时间对比,如果大于过期时间,则将其删除。为了使用便捷性,我们可以将本地存储封装个方法同一管理。
不过,这种方式是有隐藏问题的,如果用户更改了操作系统时间,比如将时间调到了过期时间之后,将导致所有缓存失效。也就是说客户端的时间是不可信的。