Vue.js + Tauri.js桌面应用中SQLite使用报错求助
问题分析与解决方案
首先,你用sqlite3包报错的核心原因是:sqlite3是Node.js原生模块,只能在Node.js环境运行,而Tauri的前端Vue代码是运行在WebView(浏览器环境)里的,两者环境不兼容,所以直接在前端代码里引用会报错。
可选解决方案
方案1:使用Tauri后端(Rust)处理数据库操作(推荐)
这是Tauri官方推荐的最佳实践,数据库操作放在后端更安全,也能正常使用SQLite:
- 在
src-tauri目录的Rust代码中,使用rusqlite库来连接和操作SQLite数据库 - 通过Tauri的IPC机制(
invoke/command)让前端Vue组件调用后端的数据库操作函数
举个简单示例:
- 后端Rust代码(
src-tauri/src/main.rs):
use tauri::State; use rusqlite::{Connection, Result}; use serde_json::Value; struct Database(Connection); #[tauri::command] fn get_users(db: State<'_, Database>) -> Result<Vec<Value>, String> { let mut stmt = db.0.prepare("SELECT * FROM barbers").map_err(|e| e.to_string())?; let users = stmt.query_map([], |row| { Ok(json!({ "id": row.get(0)?, "name": row.get(1)? })) }).map_err(|e| e.to_string())? .collect::<Result<Vec<_>, _>>().map_err(|e| e.to_string())?; Ok(users) } fn main() { let db = Connection::open("sqlite3.db").expect("Failed to open database"); tauri::Builder::default() .manage(Database(db)) .invoke_handler(tauri::generate_handler![get_users]) .run(tauri::generate_context!()) .expect("error while running tauri application"); }
- 前端Vue组件调用:
<template> <h1>Base Test</h1> </template> <script> import { invoke } from '@tauri-apps/api/tauri'; export default { name: 'data', data() { return { users: [] }; }, async mounted() { try { this.users = await invoke('get_users'); console.log(this.users); } catch (err) { console.error('Error getting users:', err); } } }; </script>
方案2:改用sql.js在前端操作数据库
如果确实需要在前端处理数据库,可以用sql.js,它是编译为WebAssembly的SQLite版本,兼容浏览器环境:
- 安装
sql.js:npm install sql.js - 注意:
sql.js默认将数据存在内存中,页面刷新后数据会丢失,如果需要持久化,要结合Tauri的文件系统API(@tauri-apps/api/fs)来读写本地数据库文件
示例代码(database.js):
import initSqlJs from 'sql.js'; import { readTextFile, writeTextFile } from '@tauri-apps/api/fs'; let db; // 初始化数据库 async function initDB() { const SQL = await initSqlJs({ locateFile: file => `/${file}` // 指向sql.js的Wasm文件 }); // 尝试读取本地数据库文件 try { const dbData = await readTextFile('sqlite3.db'); const buffer = new Uint8Array(atob(dbData).split('').map(c => c.charCodeAt(0))); db = new SQL.Database(buffer); } catch (err) { // 如果文件不存在,创建新数据库 db = new SQL.Database(); // 初始化表结构 db.run('CREATE TABLE IF NOT EXISTS barbers (id INTEGER PRIMARY KEY, name TEXT)'); } } // 获取用户数据 async function getUsers() { if (!db) await initDB(); const stmt = db.prepare('SELECT * FROM barbers'); const rows = []; while (stmt.step()) { rows.push(stmt.getAsObject()); } return rows; } // 保存数据库到本地(持久化用) async function saveDB() { if (!db) return; const data = db.export(); const base64 = btoa(String.fromCharCode(...new Uint8Array(data))); await writeTextFile('sqlite3.db', base64); } export default { getUsers, saveDB }
然后Vue组件调用:
<template> <h1>Base Test</h1> </template> <script> import dbService from '../services/database.js'; export default { name: 'data', data() { return { users: [] }; }, async mounted() { try { this.users = await dbService.getUsers(); console.log(this.users); } catch (err) { console.error('Error getting users:', err); } } }; </script>
总结
- 优先选方案1,符合Tauri的架构设计,安全性和性能更好
- 方案2适合简单场景,但要额外处理数据持久化的问题
内容的提问来源于stack exchange,提问作者Abubakr Shomirsaidov
相关产品推荐
相关产品推荐

