一、使用场景
我:你是什么?
indexDB:我也是浏览器的一种存储,跟localStorage、sessionStorage、cookie一样,可以缓存数据;
我:平时用上边说的三个就够了,你有哪些优势呢?
indexDB:localStorage跟sessionStorage存储空间5M左右,cookie只有4K,那如果要存储比5M大的数据该怎么办呢?我的存储空间要大很多,一般来说不少于250M。
我:大多数项目也不需要存这么多内容,什么时候用你呢?
indexDB:比如:
- 1、IM 相关的项目,聊天记录或者一些用户的信息,这些数据积累下来,量就比较大了;
- 2、接口比较多的页面,可以使用我做接口数据缓存,减少下次渲染时间;
- 3、某个接口返回全量数据(数万条或以上),由客户端做分页加载,可以放到我这里减少内存占用;
- 4、静态资源的缓存,可以转成base64然后用我存储;
- 等等..
- 总之上边localStorage、sessionStorage、cookie存不下的数据都可以考虑用我;
我:👍🏻👍🏻👍🏻
二、使用indexDB第三方库
为了提高开发效率,操作indexDB推荐使用github上最高star的第三方库 dexie.js
这个库使用promise封装,使用起来也比较顺手
项目中集成dexie
1、安装依赖
npm install dexie
2、创建一个db、表
- db.js
import Dexie from 'dexie';
//创建db
const db = new Dexie('myDatabase');
//创建表
db.version(1).stores({
friends: 'id, name, age', // 主键跟索引字段
});
3、操作db 更多操作参考文档
- demo.js
//增,也可以用put
await db.friends.add({
id: '1',
name: "小名",
age: 18,
});
//删
await db.friends
.where("name").equals('小名')
.delete()
//改 put操作 在对象存储中添加新对象或替换现有对象。
await db.friends.put({
id: '1',
name: "小名",
age: 19,
})
//查
await db.friends.get('1')
怎么样,有了第三方库的加持,开发是不是爽了很多,使用起来也没那么复杂;
三、项目中使用dexie缓存接口数据
1、把上边db.js封装下
- db.js
import Dexie from "dexie"
/* 当前数据库版本,修改表信息记得改版本+1 */
const version = 2;
/* 表数据 */
let tableList = [
/* 接口信息缓存 */
{
name: "requestCache",
index: "id, res",
columns: {
id: "",/* JSONString config */
res: "",/* 返回值 */
ts: 0/* 时间戳 */
},
cacheTs: 1000 * 60 * 60 * 24 * 30 /* 1月 */
},
]
class DexieDB {
db = {}
/* 初始化 */
init(dbName = "cache") {
this.db = new Dexie(dbName);
console.log("indexDB->db创建成功")
this.initTable()
}
/* 初始化table */
initTable() {
let tableObj = {}
tableList.map((item) => {
tableObj[item.name] = item.index
})
this.db.version(version).stores(tableObj)
console.log("indexDB-> 表创建成功", tableObj)
}
/* 清理缓存,可以在页面打开时候自己找地方调用,清理过期缓存 */
clearCache(){
let now = +new Date()
tableList.map(async (item) => {
const {cacheTs} = item;
if(!cacheTs) return;
let res = await this.db[item.name].where("ts").below((now-cacheTs)).delete()
console.log("indexDB->清理缓存", item.name, res)
})
}
}
export default new DexieDB()
2、封装一个链式调用工具类,请求是用的axios
export class AjaxAndCache {
constructor(params) {
//axios参数
this.params = params;
//缓存用的主键id数据
this.cacheKey = JSON.stringify(this.params)
}
//错误回调
errCB;
//接口是否返回了
cancel = false;
//读缓存
cache(cb) {
this.cancel = false;
const {
url,
method,
params,
data
} = this.params;
try {
//读取缓存
dexieDB.db.requestCache.get(this.cacheKey).then((res) => {
//如果接口返回快则直接return,不用缓存数据
if(this.cancel) return ;
cb(res?.res ?? {})
}).catch(console.error)
} catch (error) {
console.error(error)
cb({})
}
return this
}
//请求数据
then(cb) {
req.ajax(this.params).then((res) => {
const {
url,
method,
params,
data
} = this.params;
// 更新requestCache当前接口数据
try {
//存储缓存
dexieDB.db.requestCache.put({
id: this.cacheKey,
res: res,
ts: +new Date()
}).catch(console.error)
} catch (error) {
console.error(error)
}
cb(res);
this.cancel = true;
}).catch((err) => {
this.errCB && this.errCB(err)
})
return this
}
//报错
catch (cb) {
this.errCB = cb;
return this;
}
}
3、使用工具类存储并使用缓存
<template>
<div>
组件渲染
</div>
</template>
<script setup>
import {provide, onMounted, ref } from "vue";
import {AjaxAndCache} from "@/req"
const dataSource = ref(null);
const init = async () => {
new AjaxAndCache({
url: "/api/接口",
method: "get"
}).cache((res)=>{
//缓存数据
dataSource.value = res;
}).then((res)=>{
//接口数据
dataSource.value = res;
}).catch(console.error)
}
onMounted(init)
provide('dataSource', dataSource)
</script>
<style lang="less" scoped>
</style>
兼容性
结语
希望能帮大家扩展一下思路
大家根据自己业务场景判断是否需要indexDB,怎么使用