在日常开发中,前端常用的存储都是cookies、Web Storage(sessionStorage、localStorage),虽然使用简单,但也存在两个明显的弊端。
存储空间限制
:cookies 4Kb,sessionStorage、localStorage 一般是5M,对于存储更大量的结构化数据来说力不从心存取不便
:存入的内容需要经过序列化,取值的时候需要通过反序列化
而 IndexedDB 提供了这种场景的解决方案,localforage则使得IndexedDB用起来可以像Web Storage一样简单
IndexedDB
如果你觉得了解IndexedDB太麻烦,那么可以选择跳过,直接到下一节localforage😹😹😹
IndexedDB 优势
IndexedDB 是一种底层 API,用于在客户端存储大量的结构化数据(也包括文件/二进制大型对象(blobs))。
存取方便
IndexedDB 是一个事务型数据库系统 ,类似于基于 SQL 的 RDBMS。然而,不像 RDBMS 使用固定列表。
IndexedDB 是一个基于 JavaScript 的面向对象数据库 ,允许您存储和检索用键索引的对象,可以存储结构化克隆算法支持的任何对象,不需要经过序列化与反序列化。如下
存储空间大
IndexedDB 的储存空间并没有做限制。
异步存取
localStorage如果存储内容多的话会消耗内存空间,会导致页面变卡。而IndexedDB执行的操作是异步执行的,不会阻塞应用程序,可在Web Worker 使用。
兼容性好
配合localforage的优雅降级策略(后面补充),兼容性这一块完全不用操心,大胆用就对了👏👏👏👏
IndexedDB简单的使用
链接/创建库
js
let db = null;
const dbName = "testDB",
storeName = "testStore";
const openDB = () => {
// 链接数据库,不存在则创建
const DBOpenRequest = window.indexedDB.open(dbName);
DBOpenRequest.onsuccess = function (event) {
db = event.target.result;
};
DBOpenRequest.onerror = function () {
console.log("数据库打开报错");
};
DBOpenRequest.onupgradeneeded = function (event) {
// 数据库创建或升级的时候会触发
db = event.target.result;
// 创建对象库,即存储表
db.createObjectStore(storeName, {
keyPath:'key' ,
});
};
};
添加数据
js
const addData = () => {
let objectStoreRequest = db
.transaction([storeName], "readwrite") // 事务对象 指定表格名称和操作模式("只读"或"读写")
.objectStore(storeName) // 仓库对象
.add({
key: "Walk dog",
hours: 19,
minutes: 30,
day: 24,
month: "December",
year: 2014,
notified: "no",
});
objectStoreRequest.onsuccess = function () {
console.log("数据写入成功");
};
objectStoreRequest.onerror = function (event) {
console.log("数据写入失败");
throw new Error(event.target.error);
};
};
查询获取数据
js
const getData = ()=> {
let transaction = db.transaction([storeName], "readwrite"); // 事务
let objectStore = transaction.objectStore(storeName); // 仓库对象
let request = objectStore.get("Walk dog");
request.onerror = function (event) {
console.log("事务失败");
};
request.onsuccess = function (event) {
console.log("主键查询结果: ", request.result);
};
}
修改数据
js
const updateData = ()=> {
let transaction = db.transaction([storeName], "readwrite"); // 事务
let objectStore = transaction.objectStore(storeName); // 仓库对象
let request = objectStore.get("Walk dog2"); // 获取key值为Walk dog2的数据
request.onerror = function (event) {
console.log("事务失败");
};
request.onsuccess = function (event) {
const data = request.result || {key:'Walk dog2'}; // 如果不存在,则创建
console.log("主键查询结果: ", data);
data.notified = "yes";
const updateRequest = objectStore.put(data); // 入库修改
updateRequest.onsuccess = () => {
console.log("修改成功 ");
};
};
}
删除数据
js
function deleteData() {
let request = db.transaction([storeName],'readwrite').objectStore(storeName).delete('Walk dog2')
request.onsuccess = function () {
console.log('数据删除成功')
}
request.onerror = function () {
console.log('数据删除失败')
}
}
更多API可参考文档直通车
看到这,是不是有那么些放弃的想法了🤣🤣。兄嘚,莫要捉急,以下通过localforage实现更简单的操作🤔🤔🤔
localforage
localForage 是一个 JavaScript 库,通过简单类似 localStorage
API 的异步存储来改进你的 Web 应用程序的离线体验。它能存储多种类型的数据,而不仅仅是字符串。
localForage 有一个优雅降级策略,若浏览器不支持 IndexedDB 或 WebSQL,则使用 localStorage。在所有主流浏览器中都可用:Chrome,Firefox,IE 和 Safari(包括 Safari Mobile)
安装
js
npm install localforage
改进的离线存储
js
// 通过 localStorage 设置值
localStorage.setItem('key', JSON.stringify('value'));
doSomethingElse();
// 通过 localForage 完成同样功能
localforage.setItem('key', 'value').then(doSomethingElse);
// localForage 同样支持回调函数
localforage.setItem('key', 'value', doSomethingElse);
//取值
localforage.getItem('key').then((value)=>{
console.log(value)
})
// 删除
localforage.removeItem('key').then(function() { // 当值被移除后,此处代码运行
console.log('Key is cleared!');
})
//从数据库中删除所有的 key,重置数据库
localforage.clear().then(function() { // 当数据库被全部删除后,此处代码运行
console.log('Database is now empty.');
})
配置(可选)
设置 localForage 选项,详见文档
js
localforage.config({
//按顺序使用的首选驱动,默认值:[localforage.INDEXEDDB, localforage.WEBSQL, localforage.LOCALSTORAGE]
driver: [localforage.INDEXEDDB, localforage.WEBSQL, localforage.LOCALSTORAGE],
// 数据库的名称,默认值:'localforage'
name: "localforageTest",
//数据仓库的名称,默认值:'keyvaluepairs'
storeName: "localforageStore",
//数据库的大小(以字节为单位)。现在只用于WebSQL。 默认值:4980736
size: 1024 * 500,
//数据库的版本。将来可用于升级; 目前未使用。默认值:1.0
version: 1.0,
//数据库的描述,一般是提供给开发者的。默认值:''
description: "",
});
配置完后添加数据,如下
创建多个实例
当直接使用localforage时,会默认创建并使用实例。
createInstance
:创建并返回一个 localForage 的新实例。每个实例对象都有独立的数据库,而不会影响到其他实例。
js
const store1 = localforage.createInstance({
name: "store1",
storeName: "localforageStore1",
});
const store2 = localforage.createInstance({
name: "store2",
storeName: "localforageStore2",
});
const store3 = localforage.createInstance({
name: "store2",
storeName: "localforageStore3",
});
store1.setItem('store1key',{myKey:'myValue'})
store2.setItem('store2key',{myKey:'myValue'})
store3.setItem('store3key',{myKey:'myValue'})
实例删除
dropInstance
:
- 调用时,若不传参,将删除当前实例的 "数据仓库" 。
- 调用时,若参数为一个指定了
name
和storeName
属性的对象,会删除指定的 "数据仓库"。 - 调用时,若参数为一个仅指定了
name
属性的对象,将删除指定的 "数据库"(及其所有数据仓库)。
js
localforage.dropInstance()
localforage.dropInstance({
name: "store1",
})
localforage.dropInstance({
name: "store2",
storeName:'localforageStore3'
})
到这,相信你已经学会了localforage了👏👏👏👏
当然,你也可以结合其他状态管理工具(Pinia,vuex,mobx等)实现更高级的封装与使用😎😎😎