「这是我参与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 Storage
与Session 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 特性
- IndexedDB是一个事务数据库系统,索引表系统
- 使用IndexedDB执行的操作是异步完成的,以免阻塞应用程序
- 无法跨域访问数据
3.3 流程
- 打开一个数据库。
- 在数据库中创建对象库。
- 启动事务并发出请求以执行某些数据库操作,如添加或检索数据。
- 通过侦听正确的DOM事件等待操作完成。
- 对结果做一些事情(可以在请求对象上找到)。
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 兼容性
3.6 IndexedDB 的应用场景
在 IndexedDB 中,我们可以创建多个数据库,一个数据库中创建多张表,一张表中存储多条数据——这足以 hold 住复杂的结构性数据。
IndexedDB 可以看做是 LocalStorage 的一个升级,当数据的复杂度和规模上升到了 LocalStorage 无法解决的程度,我们毫无疑问可以请出 IndexedDB 来帮忙。