博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

前端浏览器Storage存储的五种方式

Posted on 2022-09-09 15:23  地霊殿~三無  阅读(2049)  评论(0编辑  收藏  举报

一、前言

最近需要整理一下前端浏览器都有哪种存储方式,一共是5种,cookies、local storage、session storage、web sql、indexedDB,本文将分别就大小,有效期,和使用方法等方面进行阐述。

二、cookies

1、大小限制

一个域名domain下,单cookie总大小在4KB以内,总条数一般有限。只适合存放身份认证信息。

2、有效期

默认是浏览器关闭就会销毁,也可以通过setMaxAge方法设置Expires/Max-age属性,来决定有效期。

cookie.setMaxAge(60*60) // 存活60*60秒
cookie.setMaxAge(-1) // 浏览器关闭就会销毁,这也是默认值
cookie.setMaxAge(0) // 特殊值0,表示改cookie作废
复制代码

3、 详细介绍

image.png

name和value是键值对,也就是常用的部分

domain指的是域名,在该域名下的请求,才会携带此cookie,且对子域名也生效,domain参数以(".")符号点开始。

path指的是cookie的有效路径,同样是会对子路径生效,path参数以("/")符号点结尾。

Expires/Max-age指的是cookie的有效期,expires是cookie失效的时间戳(服务器时间), max-age是几秒后失效,单位为秒,默认为-1。

size指的是大小,各浏览器大小不同,如下表

浏览器Cookie最大条数Cookie最大长度/单位:字节
IE 50 4095
Chrome 150 4096
FireFox 50 4097
Opera 30 4096
Safari 无限 4097

httpOnly
true: document.cookie不可见该条cookie,也不可修改,但请求还是会携带。 false: 默认值,可见可修改,请求会携带。

Secure是安全属性,若为true,则只能在https和ssl等安全协议中传输

SameSite是用来限制第三方Cookie,有三个属性值

Strict,最严格,完成禁止第三方Cookie,跨站点时,任何情况下都不会发送Cookie;
Lax是大多数情况不发送第三方Cookie,但get请求会携带;
None,不做限制,但必须Secure是true。
复制代码

Priority优先级,属性值low/medium/high,当cookie数量超出的时候,低优先级的cookie会被清除。

3、如何使用

import Cookies from 'js-cookie'
const TokenKey = '键名'
const token = 'token值'
// 存储
Cookies.set(TokenKey, token)
// 获取
Cookies.get(TokenKey)
复制代码

原生的写法

document.cookie="key=value;Max-age=60*60"
// 键值对,";"分号分隔,其余属性也是一样的写法
复制代码

三、local storage

1、大小限制

一般为5M左右,只能存储字符串格式的数据,所以存储前需要转换成json串,需要时取出再转换。

2、有效期

默认是永久生效,只有两种清除方式,第一种通过js代码控制(能写入肯定能清除),第二种是使用浏览器的 ‘清除浏览数据’ 功能。

如果有需要可以自行百度,手动实现一个api,去设置local storage的有效期

3、详细介绍

为了弥补cookie存储大小不足,在h5里新增的一项存储技术Web storage,它分为local storage 和session storage两种,本质上两种不存在区别,唯一区别的是local storage是长期存储,session storage是会话存储(标签页关闭就会清除)。而且请求时,并不会带上web storage存储的值(这点和cookie不一样)。

local storage要求是同协议,同域名,同端口,就能共享或修改同一份localStorage数据。

session storage则要求同协议,同域名,同端口,同窗口(即同个浏览器标签页)

4、如何使用

Web storage的api是一致的,除了调用前缀不同而已,下面是local storage的调用方法。

官方api有以下几种:
getItem 获取
setItem 设置
removeItem  移除
clear 清空

localStorage.getItem('key') // 获取键名为key的值
localStorage.setItem('key','value') // 设置键名为key,并赋值,若存在就会
//修改属性值,这里的value必须是字符串,若是对象可以调用JSON.stringify(obj)
//来序列化成字符串
localStorage.removeItem('key') // 移除键名为key的值
localStorage.clear('key') // 清空所有值

当然,因为local storage是数组,所以数组的增删改查也可以对其生效。不过不推荐。
复制代码

四、session storage

1、大小限制

一般为5M左右,只能存储字符串格式的数据,所以存储前需要转换成json串,需要时取出再转换。

2、有效期

标签页关闭就会清空

3、介绍和使用

这部分跟local storage一致,参照第三点

五、web sql

1、大小限制

无限制

2、有效期

刷新当前页面,or 关闭当前页面失效

3、详细介绍

Web SQL 数据库 API 并不是 HTML5 规范的一部分,但是它是一个独立的规范,引入了一组使用 SQL 操作客户端数据库的 APIs,相当于是在浏览器中内置了一个sqlite关系型数据库,不过操作是由js去操作sql来实现的。

不过web sql存在兼容性差的限制,只能在最新版的 Safari, Chrome 和 Opera 浏览器中使用,ie和Firefox则均不支持。

4、 如何使用

核心方法就三个
1.  **openDatabase**:这个方法使用现有的数据库或者新建的
数据库创建一个数据库对象。
2.  **transaction**:这个方法让我们能够控制一个事务,以及
基于这种情况执行提交或者回滚。
3.  **executeSql**:这个方法用于执行实际的 SQL 查询。
复制代码

打开or创建数据库openDatabase

// 数据库名称,版本号,描述文本,容量大小, 回调函数(非必选)
var db = openDatabase('mydb', '1.0', 'Test DB', 2 * 1024 * 1024);
复制代码

执行查询transaction,里面去调用executeSql函数,参数的基本语句和mysql的一致。

  db.transaction(function (tx) { 
      tx.executeSql('CREATE TABLE IF NOT EXISTS LOGS (id unique, log)'); 
  });
复制代码

对熟悉后端mysql数据库的码农来说,应该是小菜一碟,这里就不多赘述了,有兴趣的可以自行百度。

六、indexedDB

1、大小限制

无限制,专门用来存放大数据,存储大小一般有50m-250m(受硬盘限制),上不封顶。

2、有效期

会在本机一直保存。以下几种情况会清除。

若是浏览器的无痕模式,那在退出所有无痕窗口后,会清除indexDB;

若是浏览器设置,退出前清除浏览数据,也会清除;

若是在浏览器控制手动删除indexDB数据库,也会清除。

若是在js中调用deleteDatabase方法,也可以清除。
复制代码

3、详细介绍

indexDB是一款对象型数据库,它会在客户端本地根据网址等创建具体文件数据,indexDB(浏览器数据库)本机存储文件夹在以下路径(以google为例)。

  1)windows版本  C:\Users\ ‘当前的登录用户’\AppData\Local\Google\Chrome\User Data\Default\IndexedDB\


2)linux版本  `/home/[当前登录用户]/.config/google-chrome/Default/IndexedDB/`
复制代码

indexDB一共有以下几个特性

a、键值对储存。 主键独一无二

b、异步。 异步操作,防止操作数据库时,拖慢网页。

c、支持事务。 这意味着,如果事务中有一步失败,数据库将回滚到事务发生前的状态。

d、同源限制。 每个数据库是根据域名创建的,网页只能访问自身域名下的数据库,禁止跨域访问。

e、存储空间大。 一般浏览器会分配50m-250m这个值,但也受硬盘大小影响,可以没有上限。

f、支持二进制存储。 这点和web storage不同,意味着不需要额外转成字符串才能进行存储。

g、兼容性。

(1)IE10起支持
(2)Firefox 10、Chrome 23、Opera 15
(3)最新版的桌面版或移动版的Safari也支持IndexedDB。

4、如何使用

indexDB的使用分3步

a、打开数据库DB
b、在versionChange事件中 创建表(ObjectStore),包括定义表的键,索引规则等。
c、操作数据(增删改查,都是用事务做)

操作数据分4步
 c-1、开启事务
 c-2、获取事务中的objectStore
 c-3、通过objectStore发起操作请求
 c-4、定义请求的回调函数

复制代码

首先是打开数据库

const opendbRequest = indexedDB.open("MyDatabase", version); 
复制代码

上述的opendbRequest会有四个状态

sucess 打开成功
error 打开失败
upgradeneeded 首次打开或者数据库版本变化时会触发,先本事件,再是sucess等事件
blocked 上一次连接还没关闭
复制代码

// 注意:并不是直接打开数据库,而是发起了一个打开数据库的请求!这里当verison比现存的db版本大,或者不存在当前db的时候,就会触发一个changeVersion的事件,会触发upgradeneeded回调。

let db;

opendbRequest.onsuccess = function(event) {

    // 请求的 success 回调里面就可以获取打开的数据库了:

    db = event.target.result; // 或 opendbRequest.result

};
复制代码

打开完数据库,那就是对数据库的各种设置了

opendbRequest.onupgradeneeded = e=>{
    const db = e.target.result
    // 只有在这个回调里面,才能定义(增删改)对象仓库及对象仓库的规则!
    // 术语:对象仓库(objectStore) 相当于 MySQL中的表(table),mogodb中的repository(仓库)
    // 创建objectStore
    // 创建时 一定要注意定义好key的规范,key就相当于
    // MySQL里的主键,关于key的规范请百度查询
    const objectStore = DB.createObjectStore('myObjectStore', { keyPath: 'id' });
    // 创建索引:
    // 有联合索引,唯一索引,对数组字段建索引
    objectStore.createIndex('index_name', ['field1', 'field2', 'field3'], { unique: true })\
 }
 
复制代码

设置完,才可以用事务,对数据库里的数据进行增删查改

// 创建事务:
// 第一个参数指明事务所涉及的objectStores,如果只有一个objectStore,[]可以省略,本例可以直接写 'myObjectStore'
// 第二参数指明事务操作数据的方式,如不写 默认是 readonly,表示只能读数据 不能写。如果不仅仅是读,还有增删改数据,必须用 readwrite。
// 请注意 readwrite 事务性能较低,并且只能有一个处于活动状态。所以除非必要,不要随意使用readwrite!
let transaction = db.transaction(['myObjectStore'],'readwrite')
// 获取事务中的objectStore (**注意:** objectStore只有事务才能获取,而不能通过db直接获取)
let objectStore = transaction.objectStore('myObjectStore')
// 在事务objectStore上发起操作数据的请求:(注意只有objectStore才能发起操作数据的请求!)
// add 新增, put 不存在相同key值的,是新增;存在,是修改,
// delete 删除,get 查询 这两个参数只能传入特定对象的 key!如:let request = objectStore.delete(myKey)
let request = objectStore.add(modifyData)
// 请求成功的回调
request.onsuccess = e => {
    console.log('添加数据成功。新数据的key是:',e.target.result)
}

复制代码

如果不需要了,要删除数据库

var DBDeleteRequest = window.indexedDB.deleteDatabase('MyDatabase');

// 成功
DBDeleteRequest.onerror = function () {};
// 失败
DBDeleteRequest.onsuccess = function () {};
复制代码

本文对于indexDB的阐述不够详细,感兴趣的可以去文档里继续查看。 IndexedDB - Web API 接口参考 | MDN

也可以了解一下dexie.js, 这是对indexDB封装过的,用起来比原生的indexDB简便一些。

5、使用场景

  threejs的3d模型,一般都较大,可以异步请求,先存储到本地
  indexDB数据库,需要时再本地读取,速度比从服务端请求快得多。
  
  
  地图基础数据,特别是路段基础数据,动辄上w条数据,基本也
  得有10几m,甚至更多,也可以首次请求完存储到本地indexDB数据库。
  
  
  图片的大批量提交,blob数据也可以暂存于indexDB,避免重复
  获取,生产多余垃圾。
  
  
  离线应用,在有网络的情况下,保存服务端数据,以便离线时,
  应用能够正常使用。
  
  
  页面间共用的大数据,或者结构特别复杂的数据,此时可以选择
  用indexDB管理会简单些。
复制代码

ps: 整理不易,点个赞吧

Snipaste_2022-07-19_15-30-26.jpg


作者:地霊殿__三無
链接:https://juejin.cn/post/7127561236165689380
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
Live2D