在客户端,我们所接触到的绝大部分本地缓存方案主要有localStorage
以及sessionStorage
,其实Storage
除了这两大高频 api,另外还有IndexDB
、cookies
、WebSQL
,Trust Token(信任令牌)
,cookies
相对来说在前端接触比另外几个多点,IndexDB
在平常业务中肯定有所耳闻,至于其他的貌似还真没用过
本文是笔者关于IndexDB
的一个简单的实践示例,一起来学习下IndexDB
,因为有时候,还是真的很有用。
正文开始...
在阅读本文之前,本文主要从以下几点去探讨IndexDB
为什么会有
IndexDB
,本地localStorage
与sessionStorage
不够用吗IndexDB
有何特征以一个示例加深对于
IndexDB
的理解IndexDB
在什么情况下能为我们的业务解决什么样的问题
了解 IndexDB
根据官方 MDNIndex DB文档查询解释
IndexDB
是浏览器提供的一种可持久化数据存储方案- 支持多种类型的键,可以支持存储任何类型的数据
- 支持键检索,查询,新增,删除操作
- 在客户端浏览器可以存储大数据量,适用于离线应用
- 所有接口都是基于事件 在与
lcoalStorage
或者seesionStorage
来说,IndexDB
存储数据量更大,更强大
IndexDB 特征
你可以把IndexDB
当成一个本地的数据库,如果你要使用它。那么会有以下几个步骤
打开数据库,创建本地数据库并连接
IndexDB.open('lcoal-test')
创建对象库
db.createObjectStore('user')
基于事务操作本地数据库,实现增删查改
举个例子
本示例主要考虑最简单方式实现,也不依赖任何工程化工具,首先新建一个index.html
,在index.html
中引入vue2.7
,vue2.7
出来了,尝下鲜,主要支持组合式 api 方式了,基本api
使用上与组合式API
没有啥区别。
并且,这里我没有直接用原生IndexDB
,而是使用了官方文档推荐的一个库dexie.js,因为官方原生API
太难用了,而这个库是对原生IndexDB
的二次封装,使用起来更高效
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>初识index-db</title>
<link rel="stylesheet" href="./css/index.css" />
</head>
<body>
<div id="app">
<h3>{{lesson}}</h3>
<a href="javascript:void(0)" @click="handleAdd('add')">新增</a>
<div class="content-box">
<div class="search-bar">
<input type="text" placeholder="请输入名称" v-model="searchName" />
<span @click="handleSearch">点击搜索</span>
</div>
<template v-for="(item) in initData">
<p>
<span>{{item.name}}</span>
<span>{{item.age}}</span>
<span @click="handleAdd('edit',item)">编辑</span>
<span @click="handleDel(item)">删除</span>
</p>
</template>
</div>
<div class="wrap-modal" v-if="showDiag">
<input placeholder="请输入name" v-model="formParams.name" />
<input placeholder="请输入age" v-model="formParams.age" />
<div>
<span @click="handleSure">确认</span>
</div>
</div>
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.7.0/vue.min.js"></script>
<script src="./js/dexie.min.js"></script>
</body>
</html>
然后我们引入业务js
...
<script type="module">
// 引入hooks
import { useApp, useIndexDB } from './hooks/index.js';
const { reactive, toRefs, createApp, onMounted } = Vue;
const App = {
setup() {
const { searchName, lesson, initData, showDiag, view, formParams } = useApp();
const { add_indexDB, update_indexDB, search_indexDB, del_indexDB } = useIndexDB();
// todo 查询数据
const featchList = async (searchName = '') => {
const colletion = await search_indexDB(searchName);
initData.value = colletion;
};
onMounted(() => {
featchList();
});
// todo 编辑or添加
const handleAdd = (viewType, row) => {
searchName.value = '';
view.value = viewType;
showDiag.value = true;
// 编辑
if (view.value === 'edit') {
console.log(row);
formParams.value = {
...row
};
} else {
// 添加
formParams.value.name = '';
formParams.value.age = '';
}
};
const handleSure = () => {
showDiag.value = false;
view.value === 'edit' ? update_indexDB(formParams.value, featchList) : add_indexDB(formParams.value, featchList);
};
const handleDel = (row) => {
del_indexDB(row.id, featchList);
};
// 搜索
const handleSearch = () => {
featchList(searchName.value);
};
return {
searchName,
lesson,
showDiag,
initData,
formParams,
handleAdd,
handleSure,
handleDel,
handleSearch
};
}
};
// 绑定app
const app = new Vue(App).$mount('#app');
</script>
我们看下这里面引入的useApp, useIndexDB
// hooks/index.js
const { reactive, toRefs, ref } = Vue;
export const useApp = () => {
const useInfo = reactive({
lesson: '初识IndexDB,实现本地crud一把梭',
initData: [],
showDiag: false,
view: 'add',
searchName: '',
formParams: {
name: '',
age: ''
}
});
return {
...toRefs(useInfo)
};
};
// IndexDB hooks
export const useIndexDB = () => {
const db = new Dexie('local-test');
db.version(1).stores({
user: '++id, name, age'
});
// 添加数据
const add_indexDB = (params, callback) => {
db.user.add(params);
callback();
};
// 更新数据
const update_indexDB = (params, callback) => {
db.user.put(params);
callback();
};
// 查询
const search_indexDB = async (params) => {
const colletion = params ? await db.user.where('name').equals(params).toArray() : await db.user.toArray();
return colletion;
};
// 删除
const del_indexDB = (id, callback) => {
db.user.where('id').equals(id).delete();
callback();
};
return {
db,
add_indexDB,
update_indexDB,
search_indexDB,
del_indexDB
};
};
页面已经搭完,我们打开页面看下
- 新增
现在我们新增一条数据,在页面点击新增按钮,在applcation/Storage/IndexDB
中就会保存一条数据
当我们刷新时,数据页面仍然会保留上一次的数据
在我们新增操作,然后刷新的过程中主要发生了什么呢
其实IndexDB
主要做了以下几件事情
// hooks/index.js
// 1 建立连接,创建db
const db = new Dexie('local-test');
//2 创建了一个user的表名
db.version(1).stores({
user: '++id, name, age'
});
// 3 向user中添加数据
// 添加数据
const add_indexDB = (params, callback) => {
db.user.add(params);
callback();
};
//4 查询user表中的数据,并返回
const search_indexDB = async (params) => {
const colletion = params ? await db.user.where('name').equals(params).toArray() : await db.user.toArray();
return colletion;
};
在点击创建时,然后点击确认操作,就是在创建数据操作
...
// 点击确认会调用这个方法
const handleSure = () => {
// showDiag.value = false;
view.value === 'edit' ? update_indexDB(formParams.value, featchList) : add_indexDB(formParams.value, featchList);
};
并且注意,我们还传入了一个featchList
方法,这是在添加数据成功了,我们重新更新页面数据的一个回调
...
// todo 查询数据
const featchList = async (searchName = '') => {
const colletion = await search_indexDB(searchName);
// 页面数据赋值
initData.value = colletion;
};
...
至此一个增加操作流程就已经结束
- 更新
当我们点击编辑时,我们尝试修改名称,然后点击确认,那么此时就调用更新数据操作
// hooks/index.js
// 更新数据
const update_indexDB = (params, callback) => {
db.user.put(params);
callback();
};
我们使用的是put
方法直接就可以更新数据了
更新前
当我点击编辑
更新后
我们可以刷新右侧的刷新按钮现实对应的数据
- 删除
...
// 删除
const del_indexDB = (id, callback) => {
db.user.where('id').equals(id).delete();
callback();
}
...
删除前
删除后
当我们删除后,又可以重新添加
但是我们发现,每次只能添加一次,如果重复添加,那么此时会添加不了
主要原因是store
中的key
重复了,无法重复添加,但是你把上一条删除了,你就可以重复添加了
而且你删除后,当你刷新页面,那条数据就真的没有,当你新增一条数据,只要你不删除,那么打开页面数据就会一直在页面中。
所以IndexDB
这个相当于在前端设计了一个小型数据库能力了,真的是
什么样业务适合用 IndexDB
在上一个例子中,我们尝试用简单的一个例子去了解了IndexDB
,但是在具体实际业务中,我们也很少会使用IndexDB
去做这种杀鸡用牛刀的事,因为localStorage
与sessionStorage
也可以满足了,但如果是那种大数据量计算,如果涉及步骤操作那种,比如在这样的一个业务场景中,现在比较流行的低代码平台,拖拉拽的几个步骤就能生成一个页面,如果中途我只完成了一部分操作,页面不小心关掉了,此时如果你又让用户重新配置操作,那么体验就不会那么好,因此你可以尝试用IndexDB
去做你操作流程的本地数据持久化操作,因为IndexDB
可以存储足够大的数据量,你只需要保证你存的Schema
数据能正常渲染你的页面就行,或者你的暂存操作也可以不用服务端处理,暂存功能完全可以依赖客户端做,这样也会减少服务端的压力。
总结
基础的了解
IndexDB
,它是浏览器提供的一种可持久化缓存数据方案,相当于一个本地的数据库写了一个简单的例子,支持
IndexDB
的增删查改功能探讨了业务实际使用场景,一般用于存储大数据量,暂存操作等
本文示例code example