TagDown 扩展程序开发——前端数据持久化之 Dexie.js
TagDown 是一款开源的书签管理插件, 您可以使用扩展程序浏览、新增、修改书签,它也支持以不同方式导出书签。
除了常见的书签管理功能,还具有以下特点:
支持 ???? 新增书签,并附加额外的信息,例如
tags
、groups
等支持 ???? 导出任意书签为
json
文档以 ???? 树图的形式浏览层级结构的书签数据
一键打开多个书签,支持在 ???? 标签组内打开书签
虽然 IndexedDB 大部分操作都是异步的,但是方法返回的不是 Promise,而是基于监听事件执行回调的方式来处理操作结果,开发繁琐且代码不易于维护。
为了便于开发使用一个名为 Dexie.js 库,它对 IndexedDB APIs 进行二次封装,让调用 IndexedDB 更方便。该库大部分方法都是异步且返回 Promise。
与 IndexedDB 类似,它也有相应的不同概念,且不同的类封装了不同的方法
Dexie
该库的核心类,通过该类实例化,可以创建/连接一个 IndexedDB 数据库Table 该类表示对象库 ObjectStore
Collection 该类表示对象库中一部分数据项,可以理解为数据的查询结果
// src/ // 实例化一个数据库 const db = new Dexie('tagdown'); // 声明版本和数据结构(对象库) db.version(1).stores({ // 创建 3 个对象库,键为对象库的名称,值是对象库的中数据项的键和索引,用逗号分隔 bookmark: 'id, *tags, *groups', // 第一个是指定用作为键的属性,之后就是索引 // 加星号 * 表示数据相应属性值为数组,且将数组的每个元素作为索引 share: 'id, share', star: 'id, star', }); // 打开/创建数据库,异步操作 db.open().then((database) => { app.provide('db', database); // 通过 provide-inject 的方式将数据库对象提供给应用中其他组件使用 app.mount('#app'); }).catch((err) => { // Error occurred console.log(err); }); 复制代码
???? 根据官方的操作指南,不必判断浏览器中是否有已有同名的数据,因为每次尝试连接数据库时,Dexie 会自动判断,按需打开已有数据库或创建一个新数据库。
以下列出在项目中与数据库相关的一些主要方法
// src/composables/useBookmark.js // ... const db = inject('db'); // 基于键 id 查询数据 const getBookmarkDB = async (id) => { const bookmark = await db.bookmark.get(id); return bookmark; }; // 向 bookmark 对象库添加数据 const setBookmarkDB = async (id, bookmark) => { // console.log(bookmark); await db.bookmark.put({ id, title: bookmark.title, url: bookmark.url, faviconUrl: bookmark.faviconUrl, tags: bookmark.tags, groups: bookmark.groups, description: bookmark.description, }); }; // 基于键 id 删除数据 const deleteBookmarkDB = async (id) => { await db.bookmark.delete(id); }; 复制代码
获取索引的所有值
// src/options/App.vue // ... const db = inject('db'); onMounted(async () => { // 获取数据库中索引 tags 的所有可能的值 allTags.value = await db.bookmark.orderBy('tags').uniqueKeys(); }); 复制代码
使用 where
查询语句
// src/options/App.vue // ... const db = inject('db'); // 筛选条件是索引 share 的值为 1,并返回一个由这些数据的键值构成的数组 const getShareableIds = async () => { const result = await db.share.where('share').equals(1).primaryKeys(); return result; }; 复制代码
将查询结果转换为数组
// src/popup/components/BrowserPage.vue // ... const db = inject('db'); const starNodes = await db.star.where({ star: 1 }).toArray(); 复制代码
导入、导出 IndexedDB 数据库
// src/options/App.vue // ... import { importDB, exportDB, importInto, peakImportFile, } from 'dexie-export-import'; // ... // 导出数据库为 blob blob = await exportDB(db, { prettyJson: true, }); // ... // 导入数据库 await importInto(db, file, { overwriteValues: true, }).then(() => { console.log('import database successful!'); }).catch((err) => { console.log(err); });
作者:Benbinbin
链接:https://juejin.cn/post/7018821423414116365