localStorage 是前端本地存储的一种,其容量一般在 5M-10M 左右,用来缓存一些简略的数据基本够用,究竟定位也不是大数据量的存储。

在某些场景下 localStorage 的容量就会有点捉襟见肘,其实浏览器是有供给大数据量的本地存储的如 IndexedDB 存储数据巨细一般在 250M 以上。

弥补了localStorage容量的缺点,但是运用要比localStorage复杂一些 mdn IndexedDB

不过已经有大佬造了轮子封装了一些调用进程使其运用相对简略,下面咱们一同来看一下

localforage

localforage 具有相似localStorageAPI,它能存储多种类型的数据如 Array ArrayBuffer Blob Number Object String,而不仅仅是字符串。

这意味着咱们能够直接存 目标、数组类型的数据避免了 JSON.stringify 转换数据的一些问题。

存储其他数据类型时需求转换成上边对应的类型,比方vue3中运用 reactive 界说的数据需求运用toRaw 转换成原始数据进行保存, ref 则直接保存 xxx.value 数据即可。

装置

下载最新版别或运用npm bower 进行装置运用。

# 引进下载的 localforage 即可运用
<script src="localforage.js"></script>
<script>console.log('localforage is: ', localforage);</script>
# 经过 npm 装置:
npm install localforage
# 或经过 bower:
bower install localforage

运用

供给了与 localStorage 相同的api,不同的是它是异步的调用回来一个 Promise 目标

localforage.getItem('somekey').then(function(value) {
    // 当离线库房中的值被载入时,此处代码运转
    console.log(value);
}).catch(function(err) {
    // 当出错时,此处代码运转
    console.log(err);
});
// 回调版别:
localforage.getItem('somekey', function(err, value) {
    // 当离线库房中的值被载入时,此处代码运转
    console.log(value);
});

供给的办法有

  • getItem 依据数据的 key 获取数据 差不多回来 null
  • setItem 依据数据的 key 设置数据(存储undefined时getItem获取会回来 null
  • removeItem 依据key删去数据
  • length 获取key的数量
  • key 依据 key 的索引获取其名
  • keys 获取数据库房中一切的 key。
  • iterate代数据库房中的一切 value/key 键值对。

装备

完好装备可检查文档 这儿说个作者觉得有用的

localforage.config({ name: 'My-localStorage' }); 设置库房的姓名,不同的姓名代表不同的库房,当一个应用需求多个本地库房隔离数据的时候就很有用。

const store = localforage.createInstance({
    name: "nameHere"
});
const otherStore = localforage.createInstance({
    name: "otherName"
});
// 设置某个数据库房 key 的值不会影响到另一个数据库房
store.setItem("key", "value");
otherStore.setItem("key", "value2");

同时也支撑删去库房

// 调用时,若不传参,将删去当前实例的 “数据库房” 。
localforage.dropInstance().then(function() {
  console.log('Dropped the store of the current instance').
});
// 调用时,若参数为一个指定了 name 和 storeName 属性的目标,会删去指定的 “数据库房”。
localforage.dropInstance({
  name: "otherName",
  storeName: "otherStore"
}).then(function() {
  console.log('Dropped otherStore').
});
// 调用时,若参数为一个仅指定了 name 属性的目标,将删去指定的 “数据库”(及其一切数据库房)。
localforage.dropInstance({
  name: "otherName"
}).then(function() {
  console.log('Dropped otherName database').
});

idb-keyval

idb-keyval是用IndexedDB实现的一个超级简略的基于 promise 的键值存储。

装置

npm npm install idb-keyval

// 悉数引进
import idbKeyval from 'idb-keyval';
idbKeyval.set('hello', 'world')
  .then(() => console.log('It worked!'))
  .catch((err) => console.log('It failed!', err));
// 按需引进会摇树
import { get, set } from 'idb-keyval';
set('hello', 'world')
  .then(() => console.log('It worked!'))
  .catch((err) => console.log('It failed!', err));
get('hello').then((val) => console.log(val));

浏览器直接引进 <script src="https://cdn.jsdelivr.net/npm/idb-keyval@6/dist/umd.js"></script>

露出的全局变量是 idbKeyval 直接运用即可。

供给的办法

由于其没有中文的官网,会把比如及自己的理解附上

set 设置数据

值能够是 数字、数组、目标、日期、Blobs等,虽然老Edge不支撑null。

键能够是数字、字符串、日期,(IDB也允许这些值的数组,但IE不支撑)。

import { set } from 'idb-keyval';
set('hello', 'world')
  .then(() => console.log('It worked!'))
  .catch((err) => console.log('It failed!', err));

setMany 设置多个数据

一个设置多个值,比一个一个的设置更快

import { set, setMany } from 'idb-keyval';
// 不应该:
Promise.all([set(123, 456), set('hello', 'world')])
  .then(() => console.log('It worked!'))
  .catch((err) => console.log('It failed!', err));
// 这样做更快:
setMany([
  [123, 456],
  ['hello', 'world'],
])
  .then(() => console.log('It worked!'))
  .catch((err) => console.log('It failed!', err));

get 获取数据

假如没有键,那么val将回来undefined的。

import { get } from 'idb-keyval';
// logs: "world"
get('hello').then((val) => console.log(val));

getMany 获取多个数据

一次获取多个数据,比一个一个获取数据更快

import { get, getMany } from 'idb-keyval';
// 不应该:
Promise.all([get(123), get('hello')]).then(([firstVal, secondVal]) =>
  console.log(firstVal, secondVal),
);
// 这样做更快:
getMany([123, 'hello']).then(([firstVal, secondVal]) =>
  console.log(firstVal, secondVal),
);

del 删去数据

依据 key 删去数据

import { del } from 'idb-keyval';
del('hello');

delMany 删去多个数据

一次删去多个键,比一个一个删去要快

import { del, delMany } from 'idb-keyval';
// 不应该:
Promise.all([del(123), del('hello')])
  .then(() => console.log('It worked!'))
  .catch((err) => console.log('It failed!', err));
// 这样做更快:
delMany([123, 'hello'])
  .then(() => console.log('It worked!'))
  .catch((err) => console.log('It failed!', err));

update 排队更新数据,防止由于异步导致数据更新问题

由于 getset 都是异步的运用他们来更新数据可能会存在问题如:

// Don't do this:
import { get, set } from 'idb-keyval';
get('counter').then((val) =>
  set('counter', (val || 0) + 1);
);
get('counter').then((val) =>
  set('counter', (val || 0) + 1);
);

上述代码咱们期望的是 2 但实际结果是 1,咱们能够在第一个回调履行第二次操作。

更好的办法是运用 update 来更新数据

// Instead:
import { update } from 'idb-keyval';
update('counter', (val) => (val || 0) + 1);
update('counter', (val) => (val || 0) + 1);

将主动排队更新,所以第一次更新将计数器设置为1,第二次更新将其设置为2

clear 铲除一切数据

import { clear } from 'idb-keyval';
clear();

entries 回来 [key, value] 形式的数据

import { entries } from 'idb-keyval';
// logs: [[123, 456], ['hello', 'world']]
entries().then((entries) => console.log(entries));

keys 获取一切数据的 key

import { keys } from 'idb-keyval';
// logs: [123, 'hello']
keys().then((keys) => console.log(keys));

values 获取一切数据 value

import { values } from 'idb-keyval';
// logs: [456, 'world']
values().then((values) => console.log(values));

createStore 自界说库房

文字解说:表 === store === 商铺 一个意思

// 自界说数据库称号及表称号
// 创立一个数据库: 数据库称号为 tang_shi, 表名为 table1
const tang_shi_table1 = idbKeyval.createStore('tang_shi', 'table1')
// 向对应库房增加数据
idbKeyval.set('add', 'table1 的数据', tang_shi_table1)
// 默许创立的库房称号为 keyval-store 表名为 keyval
idbKeyval.set('add', '默许的数据')

localStorage容量太小?试试它们

运用 createStore 创立的数据库一个库只会创立一个表即:

// 同一个库有不能够有两个表,custom-store-2 不会创立成功:
const customStore = createStore('custom-db-name', 'custom-store-name');
const customStore2 = createStore('custom-db-name', 'custom-store-2');
// 不同的库 有相同的表名 这是能够的:
const customStore3 = createStore('db3', 'keyval');
const customStore4 = createStore('db4', 'keyval');

promisifyRequest

自己办理定制商铺,这个没搞太理解,看文档中说既然都用到这个了不如直接运用idb 这个库

总结

本文介绍了两个 IndexedDB 的库,用来处理 localStorage 存储容量太小的问题

localforageidb-keyval 之间我更喜欢 localforage 由于其与 localStorage 相似的api几乎没有上手成本。

假如需求愈加灵活的库能够看一下 dexie.js、PouchDB、idb、JsStore或许lovefield之类的库

感谢观看!

往期文章

  • 从零到一建立归于自己的前端组件库
  • 求求你们了,对自己代码质量有点要求!
  • 不要用vue2的思维写vue3
  • vue + element-ui动态主题及网站换肤2021,亲测可用!!!
  • vue3+elementPlus主题动态切换2022,亲测可用!
  • openlayers 实战离线地图
  • 这两个前端下载库推荐给你
  • vue3 JSX 从零开始
  • 手摸手,装备项目中全局loading