前端本地存储--从Cookie到Web Storage、IndexedDB

「这是我参与11月更文挑战的第4天,活动详情查看:2021最后一次更文挑战

1. 故事的开始:从 Cookie 说起

Cookie 的本职工作并非本地存储,而是“维持状态”。

在 Web 开发的早期,人们亟需解决的一个问题就是状态管理的问题:HTTP 协议是一个无状态协议,服务器接收客户端的请求,返回一个响应,故事到此就结束了,服务器并没有记录下关于客户端的任何信息。那么下次请求的时候,如何让服务器知道“我是我”呢?

在这样的背景下,Cookie 应运而生。

Cookie 说白了就是一个存储在浏览器里的一个小小的文本文件,它附着在 HTTP 请求上,在浏览器和服务器之间“飞来飞去”。它可以携带用户信息,当服务器检查 Cookie 的时候,便可以获取到客户端的状态。

1.1 Cookie的性能劣势

  • Cookie 不够大
  • 过量的 Cookie 会带来巨大的性能浪费
    • Cookie 是紧跟域名的。
    • 同一个域名下的所有请求,都会携带 Cookie。

2. 向前一步:Web Storage

Web Storage 是 HTML5 专门为浏览器存储而提供的数据存储机制。它又分为 Local StorageSession Storage。这两组概念非常相近,我们不妨先理解它们之间的区别,再对它们的共性进行研究。

2.1 Local Storage 与 Session Storage 的区别

  • 两者的区别在于生命周期与作用域的不同。

生命周期:

Local Storage 是持久化的本地存储,存储在其中的数据是永远不会过期的,使其消失的唯一办法是手动删除;

Session Storage 是临时性的本地存储,它是会话级别的存储,当会话结束(页面被关闭)时,存储内容也随之被释放。

作用域:

Local Storage、Session Storage 和 Cookie 都遵循同源策略。

但 Session Storage 特别的一点在于,即便是相同域名下的两个页面,只要它们不在同一个浏览器窗口中打开,那么它们的 Session Storage 内容便无法共享。

2.2 Web Storage 的特性

存储容量大: Web Storage 根据浏览器的不同,存储容量可以达到 5-10M 之间。

仅位于浏览器端,不与服务端发生通信。

2.3 应用场景

2.3.1 Local Storage

  • Local Storage 在存储方面没有什么特别的限制,理论上 Cookie 无法胜任的、可以用简单的键值对来存取的数据存储任务,都可以交给 Local Storage 来做。

  • 考虑到 Local Storage 的特点之一是持久,有时我们更倾向于用它来存储一些内容稳定的资源。比如图片内容丰富的电商网站会用它来存储 Base64 格式的图片字符串:

  • 有的网站还会用它存储一些不经常更新的 CSS、JS 等静态资源。

2.3.2 Session Storage

Session Storage 更适合用来存储生命周期和它同步的会话级别的信息。这些信息只适用于当前会话,当你开启新的会话时,它也需要相应的更新或释放。

比如微博的 Session Storage 就主要是存储你本次会话的浏览足迹:

Last URL 对应的就是你上一次访问的 URL 地址,这个地址是即时的。当你切换 URL 时,它随之更新,当你关闭页面时,留着它也确实没有什么意义了,干脆释放吧。这样的数据用 Session Storage 来处理再合适不过。

Web Storage 是对 Cookie 的拓展,它只能用于存储少量的简单数据。当遇到大规模的、结构复杂的数据时,Web Storage 也爱莫能助了。这时候我们就要清楚我们的终极大 boss——IndexedDB

3. 终极形态:IndexedDB

IndexedDB 是一个运行在浏览器上的非关系型数据库。

既然是数据库了,那就不是 5M、10M 这样小打小闹级别了。理论上来说,IndexedDB 是没有存储上限的(一般来说不会小于 250M)。它不仅可以存储字符串,还可以存储二进制数据。

3.2 特性

  1. IndexedDB是一个事务数据库系统,索引表系统
  2. 使用IndexedDB执行的操作是异步完成的,以免阻塞应用程序
  3. 无法跨域访问数据

3.3 流程

  1. 打开一个数据库。
  2. 在数据库中创建对象库。
  3. 启动事务并发出请求以执行某些数据库操作,如添加或检索数据。
  4. 通过侦听正确的DOM事件等待操作完成。
  5. 对结果做一些事情(可以在请求对象上找到)。

3.4 接口

获取indexedDB

// 获取indexedDB
export const indexedDB = (win: any = window): IDBFactory =>
  win.indexedDB || win.webkitIndexedDB || win.mozIndexedDB || win.msIndexedDB;
export const IDBTransaction = (win: any = window) =>
  win.IDBTransaction ||
  win.webkitIDBTransaction ||
  win.msIDBTransaction || { READ_WRITE: 'readwrite' };
export const IDBKeyRange = (win: any = window) =>
  win.IDBKeyRange || win.webkitIDBKeyRange || win.msIDBKeyRange;
// 检测
export const isSupportIndexedDB = () => {
  const db = indexedDB();
  if (db) {
    return true;
  } else {
    console.error(`您的浏览器不支持indexed db`);
    return false;
  }
};

复制代码

打开数据库

const request = (name,version)=>indexedDB().open(name,version)
复制代码

3.5 兼容性

image.png

3.6 IndexedDB 的应用场景

在 IndexedDB 中,我们可以创建多个数据库,一个数据库中创建多张表,一张表中存储多条数据——这足以 hold 住复杂的结构性数据。

IndexedDB 可以看做是 LocalStorage 的一个升级,当数据的复杂度和规模上升到了 LocalStorage 无法解决的程度,我们毫无疑问可以请出 IndexedDB 来帮忙。

Guess you like

Origin juejin.im/post/7031143002798030855