1. 概念

浏览器存储:是指浏览器提供的一种本地存储数据的机智,包括: CookieWebStorageIndexedDB
前端持久优化存储:通过JavaScript 在客户端进行数据持久化存储的方式,包括 LocalStoresIndexedDBFile API

特性CookieLocalStorageSessionStoresIndexedDB
数据生命周期由服务器生成,可以设置过期时间;前端采用和js-cookie等组件也可以生成除非被清理,否则一直存在;浏览器关闭也会保存在本地刷新依然存在,页面关闭就清理,不支持跨页面交互除非被清理,否则一直存在
数据存储大小4K5M5M不限制
与服务端通信每次都会携带在请求的header中,对于请求性能有影响;同时由于请求中都带着,容易出现安全问题不参与不参与不参与
特点字符串键值对在本地存储字符串键值对在本地存储字符串键值对在本地存储IndexedDB是一个非关系型数据库(不支持通过SQL语句操作)。可以存储大量数据,提供接口来查询,还可以建立索引,这些都是其他存储方案无法提供的。

2、Cookie

Cookie 设计之初不是用来做本地存储的,而是用来弥补 HTTP 在状态管理上的不足。
HTTP 协议是一个无状态的协议,客户端向服务器发请求,服务器返回响应,故事就这样结束了,但是下次发送请求如何让服务器知道你是谁呢?这种情况下就产生了 Cooike
Cookie 本质上是浏览器里面存储的文本文件,内部以键值对的方式存储,向同一个域名下发送请求,都会携带相同的 Cookie,服务器拿到 Cookie 进行分析,就能拿得到客户端的状态。它可以设置过期时间,用于在客户端和服务器端传递数据,由于每次携带 Cookie 信息,可能导致网络开销增加,并且存在安全问题,所以不适合存储大量数据。
Cookie 本职工作并不是本地存储,而是“维持状态”,HTTP 是无状态的,HTTP协议本身不对请求响应之间的通信状态保存。
Cookie 过期等配置
Cookie 分为:Session Cookie 和持久型 CookieCookie 设置中有个 HttpOnly 参数,前端浏览器使用 document.cookie 是读取不到 HttpOnly 类型的 Cookie 的,被设置为 HttpOnlyCookie 记录只能通过 HTTP 请求头发送到服务端进行读写操作,这样就避免了服务器的 Cookie 记录被 JavaScript 修改,保证了服务器验证 Cookie 的安全性。
Cookie 的内容主要包括:名字、值、过期时间、路径、域。路径和域一起构成 Cookie 的作用范围。若不设置过期时间,则表示这个 Cookie 的生命周期为浏览器会话时间,关闭浏览器窗口,Cookie 就消失。
这种生命周期为浏览器会话期的 Cookie 被称为会话Cookie会话Cookie 一般不存在硬盘上面而是保存在内存里。若设置了过期时间,浏览器就会把 Cookie 保存在硬盘上,关闭后再次打开浏览器,这些 Cookie 仍然有效,知道超过设定的过期时间,存储在硬盘上的 Cookie 可以在不同的浏览器进进程中共享,比如两个窗口。而对于保存在内存中的 Cookie ,不同的浏览器有不同的处理方式。

// 设置 Cookie
function setCookie(name, value, days) {
    let expires = "";
    if (days) {
        const date = new Date();
        date.setTime(date.getTime() + (days * 24 * 60 * 1000));
        expires = "; expires=" + date.toUTCString();
    }
    document.cookie = name + "=" + value + expires + "; path=/";
}
// 读取 Cookie
function getCookie(name) {
    const nameEQ = name + "=";
    const ca = document.cookie.split(";");
    for (let i = 0; i < ca.length; i++) {
        let c = ca[i];
        while(c.charAt(0) === " ") {
            c = c.substring(1, c.length);
        }
        if (c.indexOf(nameEQ) === 0) {
            return c.substring(nameEQ.length, c.length);
        }
    }
    return null;
}
// 删除 Cookie
function deleteCookie(name) {
    setCookie(name, "", -1)
}

// 使用
// 设置Cookie 有效期 7 天
setCookie("username", "john_doe", 7);
console.log(cookie); // "username-john_doe; expires= o4 Aug 2023 14:47:16“ GMT: path=/"

// 读取Cookie
const username = getCookie("username");
console.log(username) // "john_doe"

// 删除Cookie
deleteCookie("username")

Cookie 的作用是用来做状态存储的,但是有缺陷:

  • 容量小:Cookie 的体积上限 4KB,只能存储少量的信息。
  • 性能差:Cookie 紧跟域名,不管域名下的某个地址需不需要 Cookie,请求都会携带上完整的 Cookie,随着请求的增多,其实会造成巨大的性能浪费,因为请求携带了很多不必要的内容。
  • 不安全:由于 Cookie 以纯文本的形式在浏览器和服务器中传递,很容易被截获,然后进行一系列的修改,在 Cookie 的有效期内重新发送给服务器。在 HttpOnlyfalse 时,Cookie 信息能直接被 JS 脚本来读取。

    3、Session

    Session 是一种服务器端的机制,服务器使用类似于散列表的结构(也可能就是使用散列表)来保存信息,当程序需要为某个客户端的请求创建一个 Session 时,服务器首先检查这个客户端的请求里是否已经包含了一个 session 标识(sessionID),如果已经包含了说明以前已经为此客户端创建过session,服务器就按照 sessionID 把这个 session 检索出来使用(检索不到就会新创建一个),如果客户端请求不包含 sessionID, 则为此客户端创建一个 session ,而且生成相关联的 sessionIDsessionID 的值应该是一个既不重复,又不容易被找到的规律以仿造的字符串,这个 sessionID 将被本次响应中返回给客户端保存。

总结:

  • 服务器端存储:session 是服务器端的一种机制,用于在服务器存储用户会话数据,服务器会为每一个用户创建一个 session,并在客户端保存一个对应的 sessionID
  • 生命周期:session 的生命周期由服务器管理,可以设置 session 的过期时间,当用户长时间不活动或者超过时间,session 会被销毁。

CookieSession 对比

  • cookie 存放在浏览器上,session 存放在服务器上
  • cookie 不是很安全,可以分析存放本地的 cookie 进行 cookie欺骗
  • session 会在一定时间内保存在服务器上,当访问增多时,会占用你服务器的性能
  • 单个 cookie 保存的数据不能超过 4K,cookie 的数量也有限制通常是20个
  • 建议:将登录等重要信息存放在 session 上,其他信息如果在每个请求中携带,可以放在 cookie 中,剩下的信息本地化缓存在 Web Storage 中。

4、Web Storage

Web Storage 包括 localStoragesessionStorage,是HTML5 新增的浏览器存储机制,他们在浏览器端存储数据,不会随着请求发送到服务器,不会增加网络开销,localStorage 存储的数据没有过期时间,只能手动清除或者网站清除,sessionStorage 的数据用户关闭页面或者浏览器的时候被清除,适用于临时存储。

4.1、localStorage

localStorage 有一点和 Cookie 一样,就是针对一个域名,在同一个域名下,会存储相同的一段。它可以存储大量的数据,不会过期,保留在客户端。单个 localStorage 的大小受限, 可以利用 iframe 的方式使用多个域名来突破单个页面下 localStorage 存储数据的最大限制。

注:
浏览器多个标签页打开同一个域名时,localStorage 内容是共享的,可以监听事件 storage 来做一致性操作响应处理。
例:

标签页一:通过某种行为修改 localStorage 中某个属性值,然后数据接口依赖该属性值。
标签页二:由于 localStorage 标签页之间共享,导致标签页二数据不准确。

操作方式
接下来我们具体看看如何操作 localStorage:

const obj = { name: "sanyuan", age: 18 };
localStorage.setItem("name", "sanyuan");
localStorage.setItem("info", JSON.stringify(obj));

接着进入相同的域名时就能拿到响应的值:

const name = localStorage.ageItem("name");
const info = JSON.parse(localStorage.getItem("info"));

从这里可以看出,localStorage 其实存储的都是字符串,如果存储其他类型的数据,需要调用JSON.stringify() 方法,用 JSON.parse 来解析成对象。

应用场景
利用 localStorage 的较大容量和持久特性,可以利用 localStorage 存储一些内容稳定的资源,比如官网的 logo,或者存储 Base64 格式的图片资源等。

Cookie 和 localStorage 比较

  • localStorage 的内容上限为 5M,相比于 Cookie4k 大大增加。当然这个 5M 是针对一个域名的,因此对于一个域名时持久存储的。
  • 只存在客户端,默认不参与与服务器通信。这样就很好地避免了 Cookie 带来的性能问题和安全性。
  • 接口封装,通过 localStorage 暴露在全局,并通过它的 setItemgetItem 等方法进行操作,很方便。

4.2、sessionStorage

sessionStoragelocalStoragecookie 都是在浏览器端存储的数据,其中,sessionStorage 的概念很特别,引入了一个 ”浏览器窗口“ 的概念,sessionStorage 是在同源的同窗口(tab中),始终存在的数据。也就是说只要这个浏览器窗口没有关闭,即使刷新页面或者进入同源的另一个页面,数据仍然存在。关闭窗口后, sessionStorage 被销毁,同时 ”独立“ 的打开的不同窗口,即使是用一页面,sessionStorage 对象也是不同的。

临时存储
很多时候数据只需要在用户浏览一组页面期间使用,关闭窗口后数据就可以丢弃了,这种情况使用 sessionStorage 很方便。

sessionStorage 和 localStorage 相同点

  • 容量上限都是5M
  • 只存在客户端,默认不参与服务端通信
  • 接口封装,除了sessionStorage 名字有所变化,存储放射式、操作方式都和 localStorage 一样。

sessionStoragelocalStorage 有一个本质的区别,那就是前者只是会话级别的存储,并不是持久化存储。会话结束,也就是页面关闭,这部分 sessionStorage 清空掉了。

操作方式:

// 存储
sessionStorage.setItem("name", "sanyuan");
// 取出
sessionStorage.getItem("name");
// 清除
sessionStorage.clear();

应用场景

  • 可以用它对表单数据进行维护,将表单信息存储在里面,可以保证页面即使刷新也不会让之前的标点信息丢失。
  • 可以用它存储本次浏览记录,如果关闭页面后不需要这些记录,用 sessionStorage 比较合适。事实上微博就采取了这样的存储方式。

    5、IndexedDB

    IndexedDB 是运行在浏览器中的 非关系型数据库,为大型数据的存储提供了接口。本质上是数据库,不是和 WebStorage5M 一个量级,理论上讲这个容量是没有上限的。
    image.png

IndexedDB的存储空间(所有访问的网站总和)为磁盘可用空间的 50%,或根据浏览器的设定分配;

IndexedDB 的特性,除了拥有数据库本身的特性,比如 支持事务,存储二进制数据:

  • 键值对存储:内部采用 对象特征 存放数据,在这个对象仓库中数据采用键值对的方式存储
  • 异步操作:数据库的读写属于 I/O 操作,浏览器中对异步 I/O 提供了支持。
  • 受同源策略限制,无法跨域访问数据库。
  • 它是 NoSQL 的,不需要我们去写一些特定的 SQL 语句来对数据库操作,数据形式使用的 json
  • 一个数据库中可以包含多种对象集合,相对于 SQL 数据库来说就是多个表;在一个域名下,还可以有多个数据库。但是不能跨域访问其他域的数据库。

另外一方面,用 localStorage 只能保存字符串,如果是其他的类型,那就必须用 JSON.stringify 来转换为字符串之后保存,而 IndexedDB 则可以直接保存。此外,还具备 DBMS 的常用功能,遍历、筛选等。

indexedDB 出现的意义

  • 前端存储,已经有了 localStorageCookies, 但是他们都是比较简单的技术,而 IndexedDB 提供了类似数据库风格的数据存储和使用方式。
  • Cookies 只能是字符串,储存空间小,每次 HTTP 接受和发送都会传递 Cookies 数据,它会占用额外流量。
  • localStorage 是用 key-value 键值模式存储数据,想让 localStorage 存储对象,你需要借助 JSON.stringify() 能将对象变成字符串形式,在用 JSON.parse() 将字符串还原成对象,当存储的数据庞大时,这就不是最佳实践方案了,localStorage 就是专门为小数量数据设计的,他的 api 设计为同步。
  • IndexedDB 很合适存储大量数据,他的 API 是异步调用的,IndexedDB 使用索引存储数据,各种数据库操作放在事务中执行, IndexedDB 支持简单的数据类型,它比 localStorage 强大,API 也相对复杂,对于简单的数据,还是使用 localStorageAPI 相对复杂,对于简单的数据,还是使用 localStorage
  • IndexedDB 能提供更为复杂的查询数据方式。

IndexedDB 特点

  • 非关系型数据库(NoSql):MySQL 等数据库是关系型数据库,他们的主要特点就是数据都已一张二维表的形式存储,而 IndexedDB 是非关系型数据库,主要以键值对打的形式存储数据,每一个数据记录都有对应的主键,主键是独一无二的,不能重复,否则会推出一个错误。
  • 持久化存储:cookielocalStoragesessionStorage 等方式存储的是数据当我们清除浏览器缓存后,这些数据都会被清除掉,而使用 IndexedDB 存储的数据则不会,除非手动删除该数据库。
  • 异步操作:IndexedDB 操作时不会锁死浏览器,用户依然可以进行其他操作,这与 localStorage 形成鲜明的对比,后者是同步的,异步设计是为了防止大量数据的读写,拖慢网页的表现。
  • 支持事务:IndexedDB 支持事务(transaction),这意味着一系列的操作步骤中,只要有一步失败了,整个事务都会取消,数据库回滚到事物发生之前的状态,不存在只改写一部分数据的情况,这和 MySQL 等数据库的事务类似。
  • 同源策略:IndexedDB 同样存在同源限制,每一个数据库对应创建它的域名,网页只能访问自身域名下的数据库,而不能访问跨域的数据库。
  • 存储量大:这也是 IndexedDB 不仅可以存储字符串,还可以存储二进制数据(ArrayBuffer 对象和 Blob 对象)。

操作方式:

/**
    *打开数据库
    *@param {object} dbName 数据库的名字
    *@param {string} storeName 仓库名称
    *@param {string} version 数据库的版本
    *@param {object} 该函数会返回一个数据库实例
*/
function openDB(dbName, version = 1) {
    return new Promise((resolve, reject) => {
        // 兼容浏览器
        var indexedDB = 
            window.indexedDB ||
            window.mozIndexedDB ||
            window.webitIndexedDB ||
            window.msIndexedDB;
        let db;
        // 打开数据库,若没有则创建
        const request = indexedDB.open(dbName, version);
        // 数据库打开成功回调
        request.onsuccess = function(event){
            db = event.target.result; // 数据库对象
            console.log("数据库打开成功");
            resolve(db);
        }
        // 数据库打开失败回调;
        request.onerror = function(event) {
            console.log("数据库打开失败");
        };
        // 数据库有更新时候的回调
        request.onupgradeneeded = function(event) {
            // 数据库创建或者升级打的时候会触发
            console.log("onupgradeneeded");
            db = event.target.result; // 数据库对象;
            var objectStore;
            // 创建存储库
            objectStore = db.createObjectStore("siggnalChat", {
                keyPath: "sequenceId", // 主键
                // autoIncrement: true // 实现自增
            });
            // 创建索引,在后面查询数据的时候可以根据索引查
            objectStore.createIndex("link", "link", { unique: false });
            objectStore.createIndex("sequenceId", "sequenceId", { unique:  false });
            objectStore.createIndex("messageType", "messageType", { unique: false });
        }
    })
}

我们将创建数据库的操作封装成了一个函数,并且该函数返回一个 Promise 对象, 使得在调用的时候可以链式调用,函数主要接收两个参数:数据库名称、数据库版本。函数内部主要有三个回调函数,分别是:

  • onsucess:数据库打开成功或者创建成功的回调,这里我们将数据库实例返回了;
  • onerror: 数据库打开或者创建失败的回调;
  • onupgradeneeded: 当数据库版本有变化的时候会执行的函数,比如我们想创建新的存储库,就可以在该函数里面操作,更新数据库版本即可;

应用场景

  • IndexedDB 是异步的操作,适合存储大量数据或者需要离线访问的应用;
  • 数据可视化等界面,大量数据,每次请求会消耗很大性能;
  • 即时聊天工具,大量消息需要存储到本地;
  • 其他存储方式容量不满足时,不得已使用 IndexedDB

6、其他存储

  • WebSQL:二维表的形式存储大量数据到客户端,但目前只有 Chrome 浏览器有;
  • Application Cache:通过 manifest 配置文件在本地有选择性的存储;JavaScriptcss、图片等静态资源文件的文件缓存机制,已废弃。
  • cacheStorage:在 ServiceWorker 规范中定义的,用于保存每个 ServiceWorker 声明的 Cache 对象,未来可能替代 Application Cache 的离线方案;
  • Flash缓存:主要用于Flash,具有读写浏览器本地目录的功能;
  • File API: File API 允许前端通过 JavaScript 读取和操作用户的本地文件,可以实现将文件存储到客户端,并在需要的时候读取和处理文件数据;

7、区别

  1. localStorage

    • 存储量较大:localStorage 可以存储大量的数据,通常可以存储 5MB 的数据;
    • 持久性:localStorage 中的数据不会过期,除非用户手动清除或者网站清除,否则会一直保留在客户端;
    • 作用域:localStorage 的作用域是整个域名,即在同一个域名下所有的页面的都可以访问同一份 localStorage 数据;
  2. sessionStorage

    • 存储量大: 与 localStorage 一样,通常可以存储 5MB 数据;
    • 会话级别:sessionStorage 中的数据会在当前会话期间有效,即在用户关闭当前浏览器窗口或者标签页,数据会被清除;
    • 作用域: sessionStorage 的作用域是当前窗口或者标签页,不同窗口或标签页之间无法共享数据
  3. session

    • 服务器端存储: session 是服务器端打的一种机制,用于在服务端存储用户会话数据,服务器会为没一个用户创建一个唯一的 session,并在客户端保存一个对应的 session ID
    • 生命周期:session 的生命周期由服务器管理,可以设置 session 的过期时间,当用户长时间不活动或超过过期时间,session 会被销毁;
  4. cookies

    • 存储量小:cookies 存储量较小,一般限制在 4KB 左右;
    • 持久性:可以设置 cookies 的过期时间,可以是会话级别的,也可以是持久性的,当设置了过期时间,cookies 会在过期后被删除;
    • 作用域:cookies 的作用域是整个域名,与 localStorage 类似,在同一个域名下的所有页面都可以访问相同的 cookies 数据;
  5. IndexedDB

    • 存储容量大: IndexedDB 是一种数据库,可以存储较大量的结构化数据,一般可以存储几十MB甚至几百MB的数据;
    • 异步操作:IndexedDB 是异步的,操作数据时需要使用异步 API 进行处理;
    • 丰富的查询功能: IndexedDB 支持复杂打的数据查询和索引,可以高效的检索和处理大量数据;

8、总结

  • localStoragesessionStorageHTML5 新增的浏览器存储机制,用于在客户端存储数据;
  • session 是服务器端的存储机制,用于在服务器存储用户会话数据;
  • cookies 是在客户端和服务器端都可以操作的存储机制,用于存储少量数据,它可以设置过期时间,可以用于跟踪用户状态和实现记住登录功能;
  • localStoragesessionStoragesessioncookies 是浏览器端的存储机制,用于在客户端存储数据,容量和持久性各有不同。
  • IndexedDB 是一种高级的浏览器端数据库,存储容量大且查询效率高,但使用起来相对复杂一些,需要异步操作。

九先生
48 声望3 粉丝

打工人,打工魂!