前言
在现代前端开发中,本地数据存储和管理变得越来越重要。Vue3 作为主流的前端框架,结合 Dexie.js 这个轻量级的 IndexedDB 封装库,能够为应用提供强大的本地数据管理能力。本文将详细介绍如何将 Vue3 与 Dexie.js 结合使用,构建高效的前端数据库应用。
Dexie.js 简介
什么是 Dexie.js?
Dexie.js 是一个基于 IndexedDB 的轻量级包装库,提供了简洁的 API 和强大的查询能力,让前端本地数据库操作变得更加简单直观。
本版本直接内置了dexie.js文件不需要再用npm安装
一、项目结构概述(新建个配置表例子)
/database
├── dexie.js # Dexie.js 库文件
└── configsDB/ # 配置表数据库模块
├── types.js # 数据库常量与表结构定义
├── Database.js # Dexie 数据库实例创建
├── configsDB.js # 配置数据库操作 API
二、核心文件解析
1. dexie.js
Dexie.js 是一个轻量级的 IndexedDB 封装库,提供了更简洁的 API 用于操作浏览器本地数据库。
主要特性:
- 简洁的表定义语法
- 强大的查询 API
- Promise-based 异步操作
- 支持版本升级
- 事务支持
2. types.js
数据库常量与表结构定义文件。
// 数据库表结构配置
export const DB_TABLES = {
configs: '++id, type, data, remarks, version, createdAt, updatedAt'
};
// 数据库名称
export const DB_NAME = 'ConfigureDatabase';
// 数据库版本
export const DB_VERSION = 1;
说明:
-
DB_TABLES:定义了configs表的结构-
++id:自动递增的主键 -
type:配置类型(用于分类) -
data:配置数据内容 -
remarks:配置备注信息 -
version:配置版本号 -
createdAt:创建时间 -
updatedAt:更新时间
-
-
DB_NAME:数据库名称(结合环境变量动态生成) -
DB_VERSION:数据库版本号(用于升级)
3. Database.js
Dexie 数据库实例创建文件。
import * as Dexie from '../dexie.js';
import { DB_NAME, DB_VERSION, DB_TABLES } from './types.js';
export class AppDatabase extends Dexie.default {
constructor() {
super(DB_NAME);
this.version(DB_VERSION).stores(DB_TABLES);
}
}
// 创建数据库实例
export const db = new AppDatabase();
说明:
- 创建了
AppDatabase类,继承自Dexie.default - 在构造函数中初始化数据库名称和表结构
- 导出
db实例供其他模块使用
4. configsDB.js
配置数据库操作 API 文件。
import { ref, ***puted } from 'vue';
import { db } from '@/database/configsDB/Database';
export default function configDB() {
const configs = ref([]);
const loading = ref(false);
const error = ref(null);
// 获取所有配置
const loadConfigs = async () => {
loading.value = true;
error.value = null;
try {
configs.value = await db.configs.orderBy('createdAt').reverse().toArray();
return configs.value;
} catch (err) {
error.value = '加载配置失败';
console.error('加载配置失败:', err);
} finally {
loading.value = false;
}
};
// 添加配置
const addConfig = async (configData) => {
loading.value = true;
error.value = null;
try {
const config = {
...configData,
createdAt: new Date().toISOString().slice(0, 19).replace('T', ' '),
updatedAt: new Date().toISOString().slice(0, 19).replace('T', ' ')
};
await loadConfigs(); // 重新加载列表
const id = await db.configs.add(config);
return id;
} catch (err) {
error.value = '添加配置失败';
console.error('添加配置失败:', err);
throw err;
} finally {
loading.value = false;
}
};
// 更新配置
const updateConfig = async (id, updates) => {
loading.value = true;
error.value = null;
try {
await db.configs.update(id, {
...updates,
updatedAt: new Date().toISOString().slice(0, 19).replace('T', ' ')
});
await loadConfigs(); // 重新加载列表
return "更新成功";
} catch (err) {
error.value = '更新配置失败';
console.error('更新配置失败:', err);
throw err;
} finally {
loading.value = false;
}
};
// 删除配置
const deleteConfig = async (id) => {
loading.value = true;
error.value = null;
try {
await db.configs.delete(id);
await loadConfigs(); // 重新加载列表
return "删除成功";
} catch (err) {
error.value = '删除配置失败';
console.error('删除配置失败:', err);
throw err;
} finally {
loading.value = false;
}
};
/**
* 搜索配置
* @param {string} type - 配置类型
* @returns {Promise<Array>} - 匹配的配置数组
* .startsWithIgnoreCase(type) - 模糊
* .equals(type) - 精确
*/
const searchConfigs = async (type) => {
if (!type.trim()) {
await loadConfigs();
return;
}
loading.value = true;
try {
configs.value = await db.configs
.where('type')
.equals(type)
.toArray();
return configs.value;
} catch (err) {
error.value = '搜索配置失败';
console.error('搜索配置失败:', err);
} finally {
loading.value = false;
}
};
// 计算属性
const configCount = ***puted(() => configs.value.length);
const isEmpty = ***puted(() => configs.value.length === 0);
return {
// 数据
configs,
loading,
error,
// 计算属性
configCount,
isEmpty,
// 方法
loadConfigs,
addConfig,
updateConfig,
deleteConfig,
searchConfigs
};
}
说明:
- 基于 Vue 3 ***position API 设计
- 提供了完整的 CRUD 操作 API
- 包含加载状态和错误处理
- 提供计算属性方便使用
三、使用指南
1. 初始化与引入
import configDB from '@/database/configsDB/configsDB';
const {
configs, loading, error, // 响应式数据
configCount, isEmpty, // 计算属性
loadConfigs, addConfig, // 操作方法
updateConfig, deleteConfig,
searchConfigs
} = configDB();
2. 加载所有配置
async function fetchAllConfigs() {
try {
await loadConfigs();
console.log('所有配置:', configs.value);
} catch (err) {
console.error('加载失败:', error.value);
}
}
3. 添加配置
async function addNewConfig() {
try {
const configData = {
type: 'userSettings',
data: JSON.stringify({ theme: 'dark', fontSize: 16 }),
remarks: '用户设置配置',
version: 1
};
const id = await addConfig(configData);
console.log('添加成功,ID:', id);
} catch (err) {
console.error('添加失败:', error.value);
}
}
4. 更新配置
async function updateExistingConfig(id) {
try {
const updates = {
data: JSON.stringify({ theme: 'light', fontSize: 18 }),
version: 2
};
const result = await updateConfig(id, updates);
console.log('更新成功:', result);
} catch (err) {
console.error('更新失败:', error.value);
}
}
5. 删除配置
async function removeConfig(id) {
try {
const result = await deleteConfig(id);
console.log('删除成功:', result);
} catch (err) {
console.error('删除失败:', error.value);
}
}
6. 搜索配置
async function searchConfigsByType(type) {
try {
const results = await searchConfigs(type);
console.log('搜索结果:', results);
} catch (err) {
console.error('搜索失败:', error.value);
}
}
四、高级用法
1. 事务处理
Dexie.js 自动管理事务,但也可以显式创建事务:
import { db } from '@/database/configsDB/Database';
async function batchUpdate() {
try {
await db.transaction('rw', db.configs, async () => {
await db.configs.update(1, { version: 3 });
await db.configs.update(2, { version: 3 });
});
console.log('批量更新成功');
} catch (err) {
console.error('批量更新失败:', err);
}
}
2. 版本升级
当需要修改表结构时,可以通过升级版本号来实现:
// 在 Database.js 中
class AppDatabase extends Dexie.default {
constructor() {
super(DB_NAME);
this.version(1).stores(DB_TABLES);
// 版本 2 升级
this.version(2).stores({
configs: '++id, type, data, remarks, version, createdAt, updatedAt, isActive' // 添加 isActive 字段
});
}
}
3. 复杂查询
async function ***plexQuery() {
try {
// 查询 version > 1 且 type = 'userSettings' 的配置
const results = await db.configs
.where('version')
.above(1)
.and(config => config.type === 'userSettings')
.toArray();
console.log('复杂查询结果:', results);
} catch (err) {
console.error('查询失败:', err);
}
}
效果
五、注意事项
-
数据类型:
- IndexedDB 支持存储 JavaScript 对象、数组、字符串、数字、布尔值、Date 等
- 不支持函数、正则表达式等复杂类型
- 建议将复杂数据 JSON.stringify() 后存储
-
性能优化:
- 避免在主线程中执行大量数据操作
- 使用索引提高查询性能
- 合理使用事务减少 IO 操作
-
错误处理:
- 始终处理异步操作的错误
- 注意 IndexedDB 的配额限制
- 考虑浏览器兼容性
-
Vue 组件中使用:
- 可以在组件的 setup() 函数中直接使用
- 响应式数据会自动更新视图
- 注意在组件卸载时清理资源
六、总结
本项目使用 Dexie.js 实现了一个配置数据库模块,提供了完整的 CRUD 操作 API,基于 Vue 3 ***position API 设计,方便在 Vue 组件中使用。通过合理使用 IndexedDB,可以在浏览器端实现数据持久化,提高应用的性能和用户体验。
扩展阅读:
- Dexie.js 官方文档
- IndexedDB 官方文档