Electron框架中實現(xiàn)數(shù)據庫的連接、讀取和寫入詳細方案
前言
在 Electron 框架中實現(xiàn)數(shù)據庫的連接、讀取和寫入,核心思路是在主進程中處理數(shù)據庫邏輯(避免敏感信息暴露),通過 IPC(進程間通信)與渲染進程交互。以下是詳細實現(xiàn)方案(以本地嵌入式數(shù)據庫 SQLite 為例,兼顧其他數(shù)據庫思路)。
一、技術選型與準備
1. 數(shù)據庫選擇
- 推薦 SQLite:嵌入式數(shù)據庫,無需獨立服務器,數(shù)據存儲在本地文件,適合 Electron 桌面應用。
- 其他數(shù)據庫(MySQL/PostgreSQL):需額外部署服務器,適合多端共享數(shù)據場景。
2. 核心依賴
electron:Electron 框架核心。sqlite3:SQLite 的 Node.js 驅動(異步操作)。electron-rebuild:解決原生模塊(如sqlite3)與 Electron 的兼容性問題。
3. 項目初始化
# 創(chuàng)建項目 mkdir electron-db-demo && cd electron-db-demo npm init -y # 安裝依賴 npm install electron sqlite3 --save npm install electron-rebuild --save-dev
4. 重建原生模塊(關鍵步驟)
sqlite3是原生模塊,需與 Electron 的 Node 版本匹配,執(zhí)行重建:
# 配置重建腳本(package.json中添加)
"scripts": {
"rebuild": "electron-rebuild -f -w sqlite3"
}
# 執(zhí)行重建
npm run rebuild
二、實現(xiàn)核心邏輯
1. 項目結構
electron-db-demo/ ├─ main.js # 主進程(數(shù)據庫操作+窗口管理) ├─ preload.js # 預加載腳本(安全暴露IPC接口) ├─ index.html # 渲染進程(UI+用戶交互) └─ package.json
2. 主進程(main.js):數(shù)據庫操作 + IPC 監(jiān)聽
主進程負責數(shù)據庫連接、CRUD 操作,并通過ipcMain接收渲染進程的請求。
const { app, BrowserWindow, ipcMain } = require('electron');
const sqlite3 = require('sqlite3').verbose();
const path = require('path');
// 數(shù)據庫文件路徑(存放在Electron默認的用戶數(shù)據目錄,避免權限問題)
const dbPath = path.join(app.getPath('userData'), 'mydb.db');
// 初始化數(shù)據庫連接
let db;
function initDB() {
return new Promise((resolve, reject) => {
db = new sqlite3.Database(dbPath, (err) => {
if (err) {
console.error('數(shù)據庫連接失敗:', err.message);
reject(err);
} else {
console.log('數(shù)據庫連接成功');
// 創(chuàng)建示例表(如users表)
db.run(`CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
age INTEGER
)`, (err) => {
if (err) reject(err);
else resolve();
});
}
});
});
}
// 封裝數(shù)據庫操作(Promise化,避免回調地獄)
const dbHelper = {
// 插入數(shù)據
insert: (table, data) => {
return new Promise((resolve, reject) => {
const keys = Object.keys(data).join(',');
const placeholders = Object.keys(data).map(() => '?').join(',');
const values = Object.values(data);
const sql = `INSERT INTO ${table} (${keys}) VALUES (${placeholders})`;
db.run(sql, values, function(err) {
if (err) reject(err);
else resolve({ id: this.lastID }); // 返回插入的ID
});
});
},
// 查詢數(shù)據(全部)
queryAll: (table) => {
return new Promise((resolve, reject) => {
const sql = `SELECT * FROM ${table}`;
db.all(sql, (err, rows) => {
if (err) reject(err);
else resolve(rows);
});
});
}
};
// 創(chuàng)建窗口
function createWindow() {
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, 'preload.js'), // 預加載腳本
contextIsolation: true // 開啟上下文隔離(安全要求)
}
});
mainWindow.loadFile('index.html');
}
// 初始化流程
app.whenReady().then(async () => {
await initDB(); // 等待數(shù)據庫初始化完成
createWindow();
// IPC監(jiān)聽:處理渲染進程的數(shù)據庫請求
// 1. 插入數(shù)據
ipcMain.handle('db-insert', async (event, table, data) => {
try {
return await dbHelper.insert(table, data);
} catch (err) {
throw err; // 拋出錯誤,讓渲染進程捕獲
}
});
// 2. 查詢所有數(shù)據
ipcMain.handle('db-query-all', async (event, table) => {
try {
return await dbHelper.queryAll(table);
} catch (err) {
throw err;
}
});
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) createWindow();
});
});
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') app.quit();
});
3. 預加載腳本(preload.js):安全暴露 IPC 接口
由于 Electron 開啟上下文隔離后,渲染進程無法直接訪問ipcRenderer,需通過預加載腳本暴露有限接口。
const { contextBridge, ipcRenderer } = require('electron');
// 暴露安全的IPC接口給渲染進程(僅允許必要操作)
contextBridge.exposeInMainWorld('electronAPI', {
// 插入數(shù)據
dbInsert: (table, data) => ipcRenderer.invoke('db-insert', table, data),
// 查詢所有數(shù)據
dbQueryAll: (table) => ipcRenderer.invoke('db-query-all', table)
});
4. 渲染進程(index.html):UI 交互 + 調用數(shù)據庫
渲染進程負責用戶交互(輸入數(shù)據、觸發(fā)操作),通過預加載暴露的接口調用主進程的數(shù)據庫邏輯。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Electron數(shù)據庫示例</title>
</head>
<body>
<h1>用戶管理</h1>
<!-- 插入數(shù)據表單 -->
<div>
<input type="text" id="name" placeholder="姓名">
<input type="number" id="age" placeholder="年齡">
<button onclick="addUser()">添加用戶</button>
</div>
<!-- 數(shù)據展示 -->
<div>
<h3>用戶列表</h3>
<ul id="userList"></ul>
</div>
<script>
// 調用預加載暴露的API
const { electronAPI } = window;
// 添加用戶(寫入數(shù)據庫)
async function addUser() {
const name = document.getElementById('name').value;
const age = document.getElementById('age').value;
if (!name || !age) return alert('請輸入姓名和年齡');
try {
const result = await electronAPI.dbInsert('users', { name, age: Number(age) });
alert(`添加成功!ID: ${result.id}`);
loadUsers(); // 刷新列表
} catch (err) {
alert(`添加失?。?{err.message}`);
}
}
// 加載用戶(讀取數(shù)據庫)
async function loadUsers() {
try {
const users = await electronAPI.dbQueryAll('users');
const list = document.getElementById('userList');
list.innerHTML = users.map(u => `<li>${u.id}: ${u.name} (${u.age}歲)</li>`).join('');
} catch (err) {
alert(`查詢失?。?{err.message}`);
}
}
// 頁面加載時初始化列表
window.onload = loadUsers;
</script>
</body>
</html>
三、運行與測試
在package.json中添加啟動腳本:
"scripts": {
"start": "electron .",
"rebuild": "electron-rebuild -f -w sqlite3"
}
執(zhí)行npm start即可啟動應用,測試添加用戶和查詢功能。
四、其他數(shù)據庫適配思路
1. MySQL/PostgreSQL
安裝對應驅動:
npm install mysql2(MySQL)或npm install pg(PostgreSQL)。主進程中通過驅動連接數(shù)據庫(需配置 host、user、password 等):
// MySQL示例(main.js中) const mysql = require('mysql2/promise'); const connection = await mysql.createConnection({ host: 'localhost', user: 'root', password: '123456', database: 'mydb' });后續(xù) CRUD 操作通過 SQL 語句執(zhí)行(與 SQLite 邏輯類似,替換
dbHelper即可)。
2. 關鍵注意事項
- 安全性:數(shù)據庫憑證(如 MySQL 密碼)不要硬編碼,可加密存儲在本地配置文件。
- 路徑處理:本地數(shù)據庫文件(如 SQLite)優(yōu)先使用
app.getPath('userData')(用戶數(shù)據目錄),避免權限問題。 - 錯誤處理:所有數(shù)據庫操作需捕獲錯誤并返回給渲染進程,避免應用崩潰。
通過以上方案,可在 Electron 中實現(xiàn)安全、穩(wěn)定的數(shù)據庫讀寫功能,適配本地或遠程數(shù)據庫場景。
總結
到此這篇關于Electron框架中實現(xiàn)數(shù)據庫的連接、讀取和寫入詳細方案的文章就介紹到這了,更多相關Electron數(shù)據庫連接、讀取和寫入內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
javascript版的in_array函數(shù)(判斷數(shù)組中是否存在特定值)
這篇文章主要介紹了javascript版的in_array函數(shù)(判斷數(shù)組中是否存在特定值),需要的朋友可以參考下2014-05-05
JavaScript中的"=、==、==="區(qū)別講解
今天小編就為大家分享一篇關于JavaScript中的"=、==、==="區(qū)別講解,小編覺得內容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2019-01-01

