安裝sqlite
npm i sqlite3
在main.js中使用ipcMain創建相關函數
記住要導入包
app.whenReady().then(() => {
createWindow()
dbInit()
})
const sqlite3 = require('sqlite3').verbose()
let db
const dbInit = () => {
// Ensure the directory exists
const dbPath = path.join(__dirname, 'data', 'data.db')
fs.mkdirSync(path.dirname(dbPath), { recursive: true })
// Open SQLite database
db = new sqlite3.Database(dbPath, (err) => {
if (err) {
console.error('Error opening database', err)
} else {
console.log('Database opened successfully')
}
})
// Create a table if not exists
db.run('CREATE TABLE IF NOT EXISTS kv_store (key TEXT PRIMARY KEY, value TEXT)', (err) => {
if (err) {
console.error('Error creating table', err)
}
})
}
// 處理IPC通信
ipcMain.handle('set-data', (event, key, value) => {
return new Promise((resolve, reject) => {
db.run('INSERT OR REPLACE INTO kv_store (key, value) VALUES (?, ?)', [key, value], (err) => {
if (err) {
reject(err)
} else {
resolve()
}
})
})
})
ipcMain.handle('get-data', (event, key) => {
return new Promise((resolve, reject) => {
db.get('SELECT value FROM kv_store WHERE key = ?', [key], (err, row) => {
if (err) {
reject(err)
} else {
resolve(row ? row.value : null)
}
})
})
})
這段代碼在一個 Electron 應用程序中初始化了一個 SQLite 數據庫,並確保在創建或打開數據庫之前,數據庫所在的目錄已經存在。此外,還設置了 IPC(進程間通信)處理器,用於在主進程和渲染進程之間進行數據傳遞。以下是這段代碼的詳細解釋:
1. 應用程序初始化:
app.whenReady()
方法會在 Electron 應用程序完全就緒後運行createWindow()
和dbInit()
。createWindow()
是一個創建應用程序主窗口的函數(在代碼中未顯示)。dbInit()
被調用來初始化 SQLite 數據庫。
2. SQLite 數據庫初始化 (dbInit()
):
- 使用
path.join
構造dbPath
,指定數據庫文件 (data.db
) 的位置,位於data
目錄中。 - 使用
fs.mkdirSync
確保目錄存在。{ recursive: true }
選項允許創建嵌套目錄(如果它們不存在)。 sqlite3.Database
構造函數用來打開數據庫。如果數據庫文件不存在,它將被創建。- 創建名為
kv_store
的表格(如果它尚未存在),該表格用於存儲鍵值對。
3. IPC 通信:
- 設置了兩個 IPC 處理器來與 SQLite 數據庫交互:
set-data
: 在kv_store
表格中插入或替換一個鍵值對。get-data
: 從kv_store
表格中檢索與鍵對應的值。
如果你的electron的main.ts開啓了 contextIsolation: true,
https://www.electronjs.org/zh/docs/latest/tutorial/context-isolation
那麽就需要preload.ts裏面把相關功能暴露給渲染進程了(可以在vue中調用完成存儲功能)
preload.ts
const { contextBridge } = require('electron')
const ipcRender = require('electron').ipcRenderer
contextBridge.exposeInMainWorld('api', {
ipcRender: ipcRender,
getData: (key: string) => ipcRender.invoke('get-data', key),
setData: (key: string, value: string) => ipcRender.invoke('set-data', key, value)
)}
然後我們就可以在vue中使用,如下
<!-- eslint-disable vue/multi-word-component-names -->
<script lang="ts" setup>
import { checkServerStatus } from '@/api/checkHealth'
import { ShowNotification } from '@/utils/notification'
import { onMounted, reactive } from 'vue'
const api = window.api
console.log(api)
async function check() {
let res = await checkServerStatus(form_url.url)
if (res) {
console.log('正常')
ShowNotification('服務器驗證', '服務器驗證成功', 'success')
} else {
console.log('不正常')
ShowNotification('服務器驗證', '服務器驗失敗', 'error')
}
}
const form_url = reactive({
url: ''
})
const form_login = reactive({
username: '',
token: ''
})
async function setData() {
try {
await api.setData('username', form_login.username)
await api.setData('token', form_login.token)
await api.setData('url', form_url.url)
console.log('Data saved')
} catch (error) {
console.error('Error saving data', error)
}
}
async function getData() {
try {
const value = await api.getData('username')
console.log('Data retrieved:', value)
} catch (error) {
console.error('Error retrieving data', error)
}
}
onMounted(async () => {
try {
form_url.url = await api.getData('url')
form_login.username = await api.getData('username')
form_login.token = await api.getData('token')
console.log('Data fetched')
} catch (error) {
console.log(error)
}
})
</script>
<template>
<el-header>
<h2>Gotify配置頁</h2>
</el-header>
<el-main class="container">
<el-form :model="form_url" class="url-container">
<el-form-item label="url">
<el-input v-model="form_url.url"></el-input>
</el-form-item>
<el-form-item label-width="0">
<el-button type="primary" @click="check">驗證</el-button>
</el-form-item>
</el-form>
<el-form :model="form_login">
<el-form-item label="username">
<el-input v-model="form_login.username"></el-input>
</el-form-item>
<el-form-item label="token">
<el-input type="password" v-model="form_login.token"></el-input>
</el-form-item>
<el-form-item label-width="0">
<el-button type="primary" @click="setData">提交信息</el-button>
<el-button type="primary" @click="getData">查看信息</el-button>
</el-form-item>
</el-form>
</el-main>
<el-footer></el-footer>
</template>
<style lang="scss" scoped>
.container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 80%;
margin: 0 auto;
padding: 20px;
background-color: #f9f9f9;
border-radius: 8px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}
.url-container {
display: flex;
flex-direction: row;
}
</style>
const api = window.api
這裏的window.api其實就是我們在preload.ts中暴露的api對象,裏面存儲著我們從ipcMain傳入渲染進程的函數
這樣的話,儅vue頁面挂載的時候,就會獲取sqlite中的數據,儅需要存儲值得時候,就可以通過點擊按鈕調用setData,然後與主進程通信,完成存儲