NodeJs 桌面开发学习 electron.js (一)
今天开始学习NodeJs 关于 桌面应用的内容,长期目标是 React + electron 实现一个桌面应用。
今天先实现一个简单的目标,搭建一个Electron + ts 项目架构,并实现主业务线程 和前端渲染线程的交互
一、代码结构和配置
例子项目结构大致如下:
package.json
{"name": "electron-ts-demo","version": "1.0.0","main": "dist/main.js","scripts": {"build": "tsc && xcopy /y src\\renderer\\*.html dist\\renderer\\","watch": "tsc -w","start": "electron .","dev": "concurrently \"npm run watch\" \"npm run start\""},"devDependencies": {"concurrently": "^9.2.0","electron": "^37.3.0","typescript": "^5.3.2"},"dependencies": {}
}
这里用到一个concurrently 包 是实现多条命令并行执行的工具。
tsconfig.json
{"compilerOptions": {"target": "ES2020","module": "commonjs","sourceMap": true,"outDir": "dist","strict": true,"esModuleInterop": true,"skipLibCheck": true},"include": ["src/**/*"]
}
二、代码实现
preload.ts
预处理实现
import { contextBridge, ipcRenderer } from 'electron';contextBridge.exposeInMainWorld('electronAPI', {sendMessage: (message: string) => ipcRenderer.send('message-from-renderer', message),onReply: (callback: (response: string) => void) => ipcRenderer.on('message-reply', (event, response) => callback(response))
});
实现渲染线程(页面) 发送信息到 主线程,主返回信息到渲染线程 (通过回调的形式)
main.ts
import { app, BrowserWindow, ipcMain } from 'electron';
import path from 'path';let mainWindow: BrowserWindow;function createWindow() {mainWindow = new BrowserWindow({width: 800,height: 600,webPreferences: {preload: path.join(__dirname, 'preload.js'),contextIsolation: true}});mainWindow.loadFile('dist/renderer/index.html');ipcMain.on('message-from-renderer', (event, msg: string) => {console.log('Received:', msg);event.reply('message-reply', `Main process received: ${msg}`);});
}app.whenReady().then(() => {createWindow();//macBook 兼容app.on("activate", () => {if (BrowserWindow.getAllWindows().length === 0) {createWindow();}});
});app.on("window-all-closed", () => {if (process.platform !== "darwin") {app.quit();}
});
上面实现了一个简单的生成一个窗口的例子。使用我们预先准备的preload.js预处理。
通过 ipcMain 监听 发生消息和返回回调。
index.html
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>Electron TS Demo</title><style>body {font-family: Arial;padding: 20px;}button {padding: 8px 16px;}</style></head><body><h1>Electron + TypeScript Demo</h1><button id="sendBtn">Send Message</button><div id="response"></div><script src="renderer.js"></script></body>
</html>
renderer.ts
const sendBtn = document.getElementById('sendBtn')!;
const responseDiv = document.getElementById('response')!;sendBtn.addEventListener('click', () => {console.log("sendBtn Click");window?.electronAPI.sendMessage('Hello from TypeScript');
});window?.electronAPI.onReply((response: string) => {console.log(response);responseDiv.textContent = response;
});
这里添加监听 给主线程发送消息,通过 window.electronAPI 预处理暴露到主页面的对象设置监听方法监听主线程 返回消息。