IndexDB实现一个本地数据库的增删查改

简介: 在客户端,我们所接触到的绝大部分本地缓存方案主要有localStorage以及sessionStorage,其实Storage除了这两大高频api,另外还有IndexDB、cookies、WebSQL,Trust Token(信任令牌),cookies相对来说在前端接触比另外几个多点

在客户端,我们所接触到的绝大部分本地缓存方案主要有localStorage以及sessionStorage,其实Storage除了这两大高频api,另外还有IndexDBcookiesWebSQL,Trust Token(信任令牌)cookies相对来说在前端接触比另外几个多点,IndexDB在平常业务中肯定有所耳闻,至于其他的貌似还真没用过🤣


本文是笔者关于IndexDB的一个简单的实践示例,一起来学习下IndexDB,因为有时候,可能真的很有用。


正文开始...


在阅读本文之前,本文主要从以下几点去探讨IndexDB


  • 为什么会有IndexDB,本地localStoragesessionStorage不够用吗
  • IndexDB有何特征
  • 以一个示例加深对于IndexDB的理解
  • IndexDB在什么情况下能为我们的业务解决什么样的问题


了解IndexDB


根据官方MDNIndex DB[1]文档查询解释


  • 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[2],因为官方原生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
  }
}

页面已经搭完,我们打开页面看下

d09d2ce51f77eac097058480e5d2ec81.png

  • 新增


现在我们新增一条数据,在页面点击新增按钮,在applcation/Storage/IndexDB中就会保存一条数据

7f45b7d11da0341ccca044343586bca7.png

当我们刷新时,数据页面仍然会保留上一次的数据


在我们新增操作,然后刷新的过程中主要发生了什么呢


其实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方法直接就可以更新数据了


更新前

99163b73f437ce2ef19fd1d98a9de964.png

当我点击编辑


更新后


9867a3b2c2d341d5f383fd40e77cd18a.png

们可以刷新右侧的刷新按钮现实对应的数据


  • 删除


...
// 删除
const del_indexDB = (id, callback) => {
  db.user.where('id').equals(id).delete();
  callback();
}
...

删除前

5c4d3c30cd422fc4ea2554fd5197d2b2.png

删除后

e5a81e5450e687330e24495b65bc8e25.png

我们删除后,又可以重新添加


但是我们发现,每次只能添加一次,如果重复添加,那么此时会添加不了

3bf66080d204ba9f2322a442405033f4.png

主要原因是store中的key重复了,无法重复添加,但是你把上一条删除了,你就可以重复添加了


而且你删除后,当你刷新页面,那条数据就真的没有,当你新增一条数据,只要你不删除,那么打开页面数据就会一直在页面中。


所以IndexDB这个相当于在前端设计了一个小型数据库能力了


什么样业务适合用IndexDB


在上一个例子中,我们尝试用简单的一个例子去了解了IndexDB,但是在具体实际业务中,我们也很少会使用IndexDB去做这种杀鸡用牛刀的事,因为localStoragesessionStorage也可以满足了,但如果是那种大数据量计算,如果涉及步骤操作那种,比如在这样的一个业务场景中,现在比较流行的低代码平台,拖拉拽的几个步骤就能生成一个页面,如果中途我只完成了一部分操作,页面不小心关掉了,此时如果你又让用户重新配置操作,那么体验就不会那么好,因此你可以尝试用IndexDB去做你操作流程的本地数据持久化操作,因为IndexDB可以存储足够大的数据量,你只需要保证你存的Schema数据能正常渲染你的页面就行,或者你的暂存操作也可以不用服务端处理,暂存功能完全可以依赖客户端做,这样也会减少服务端的压力。


总结


  • 基础的了解IndexDB,它是浏览器提供的一种可持久化缓存数据方案,相当于一个本地的数据库
  • 写了一个简单的例子,支持IndexDB的增删查改功能
  • 探讨了业务实际使用场景,一般用于存储大数据量,暂存操作等
  • 本文示例code example[3]


相关文章
|
6月前
|
XML Java 数据库连接
如何使用MyBatis框架实现对数据库的增删查改?
如何使用MyBatis框架实现对数据库的增删查改?
|
2月前
|
SQL Java 关系型数据库
MySQL数据库基础:增删查改
本文详细介绍了数据库中常用数据类型的使用方法及其在Java中的对应类型,并演示了如何创建表、插入数据、查询数据(包括全列查询、指定列查询、去重查询、排序查询、条件查询和分页查询)、修改数据以及删除数据。此外,还特别强调了处理NULL值时的注意事项,以及在执行修改和删除操作时应谨慎使用条件语句,以避免误操作导致的数据丢失。
74 14
MySQL数据库基础:增删查改
|
6月前
|
存储 数据处理 数据库
深入了解达梦数据库的增删查改操作:从入门到精通
深入了解达梦数据库的增删查改操作:从入门到精通
419 4
|
SQL 安全 关系型数据库
MySQL数据库中的增删查改(MySQL最核心,工作中最常用的部分)
MySQL数据库中的增删查改(MySQL最核心,工作中最常用的部分)
638 0
|
6月前
|
关系型数据库 MySQL 数据处理
『 MySQL数据库 』表的增删查改(CRUD)之表的数据插入及基本查询(下)
『 MySQL数据库 』表的增删查改(CRUD)之表的数据插入及基本查询(下)
|
6月前
|
关系型数据库 MySQL 数据库
『 MySQL数据库 』表的增删查改(CRUD)之表的数据插入及基本查询(上)
『 MySQL数据库 』表的增删查改(CRUD)之表的数据插入及基本查询(上)
|
SQL Java 关系型数据库
JDBC(常用类与接口、实现数据库的增删查改)
1.Connection接口常用方法、2.DriverMange类、3.Statement接口,4.实现表的数据更新(增、改、删),5.实现数据查找(ResultSet接口),6.PreparedStatement 数据更新
123 0
JDBC(常用类与接口、实现数据库的增删查改)
|
SQL 关系型数据库 MySQL
MySQL数据库操作篇2(表的增删查改&约束)
MySQL数据库操作篇2(表的增删查改&约束)
100 0
|
存储 SQL 安全
一文搞懂MySQL数据库基础与MySQL表的增删查改(初阶)
当我们创建数据库没有指定字符集和校验规则时,系统使用默认字符集:utf8,校验规则是:utf8_general_ci
一文搞懂MySQL数据库基础与MySQL表的增删查改(初阶)
|
SQL 数据库
数据库增删查改联表操作的sql语句
数据库增删查改联表操作的sql语句
298 0