最小示例
目录结构
- assets
- index.html
- render.js
- handle.js
- main.js
- preload.js
main.js 入口
javascript
const path = require('path')
const { app, BrowserWindow, ipcMain ,Menu} = require('electron');
// app.name 程序名
// 窗口相关的方法
const handle = require("./handle")
function createWindow() {
// 创建一个浏览器窗口
const mainWin = new BrowserWindow({
minWidth: 850,
minHeight: 600,
resizable: true, // 允许窗口调整大小
frame: false, // 禁用默认的窗口装饰 开启不能拖动
webPreferences: {
preload: path.join(__dirname, './preload.js'),
nodeIntegration: true // 允许在渲染进程中使用 Node.js API
},
transparent: true,
});
const menu = Menu.buildFromTemplate([
{
label: "打开",
submenu: [
{//向渲染器(浏览器进程)发送
click: () => mainWin.webContents.send('update-counter', 1),
label: '按钮1'
},
{//向渲染器(浏览器进程)发送
click: () => mainWin.webContents.send('update-counter', -1),
label: '按钮2'
}
]
}
])
Menu.setApplicationMenu(menu)
// ipcMain创建监听器监听ipcRenderer发送的消息
ipcMain.on('set-title', handle.SetTitle)//模式1同步 建议仅单向通行,也可双向 查看官网文档
ipcMain.handle('dialog:openFile', handle.FileOpen)//模式2异步 可双向 推荐
// 加载应用程序的主界面
// mainWin.loadFile('assets/index.html');
mainWin.loadURL('http://127.0.0.1:5173/')
// 打开开发工具
// mainWin.webContents.openDevTools()
// 监听窗口调整大小事件
// mainWin.on('resize', () => {
// const { width, height } = mainWindow.getBounds();// 获取窗口的大小
// mainWindow.webContents.send('window-resized', { width, height });
// });
}
// 当 Electron 完成初始化并准备创建浏览器窗口时,调用 createWindow 函数
app.whenReady().then(() => {
createWindow();
// 如果没有窗口打开则打开一个窗口 (macOS)
app.on('activate', () => { if (BrowserWindow.getAllWindows().length === 0) createWindow() })
});
// 关闭所有窗口时退出应用 (Windows & Linux)
app.on('window-all-closed', () => { if (process.platform !== 'darwin') app.quit() })preload.js
javascript
const { contextBridge, ipcRenderer } = require('electron')
// 所有的 Node.js API接口 都可以在 preload 进程中被调用.
// 它拥有与Chrome扩展一样的沙盒。
// 将myApi导入到window对象中
contextBridge.exposeInMainWorld('myApi', {
desktop: true
})
// 将electronAPI导入到window对象中
contextBridge.exposeInMainWorld('electronAPI', {
// ipcRenderer发送消息给监听器ipcMain
//向主程序内
setTitle: (title) => ipcRenderer.send('set-title', title),//模式1同步
openFile: () => ipcRenderer.invoke('dialog:openFile'),//模式2异步
//向浏览器内
handleCounter: (callback) => ipcRenderer.on('update-counter', callback),
})
// 通过预加载脚本从渲染器访问Node.js
// 访问 Node.js process.versions 对象,并运行一个基本的 replaceText 辅助函数将版本号插入到 HTML 文档中。
window.addEventListener('DOMContentLoaded', () => {
const replaceText = (selector, text) => {
const element = document.getElementById(selector)
if (element) element.innerText = text
}
for (const dependency of ['chrome', 'node', 'electron']) {
replaceText(`${dependency}-version`, process.versions[dependency])
}
})handle.js
javascript
const { BrowserWindow, dialog } = require('electron')
/**
* 修改打开的窗口名字
* @param {Window} event
* @param {string} title
*/
function SetTitle(event, title) {
const webContents = event.sender
const win = BrowserWindow.fromWebContents(webContents)
win.setTitle(title)
}
/**
* 打开文件选择
* @returns
*/
async function FileOpen() {
const { canceled, filePaths } = await dialog.showOpenDialog()
if (!canceled) {
return filePaths[0]
}
}
module.exports = {
SetTitle,
FileOpen,
}index.html 前端
javascript
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'" />
<meta http-equiv="X-Content-Security-Policy" content="default-src 'self'; script-src 'self'" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
Current value: <strong id="counter">0</strong>
<h1>你好!</h1>
我们正在使用 Node.js <span id="node-version"></span>,
Chromium <span id="chrome-version"></span>,
和 Electron <span id="electron-version"></span>.
<br>
Title: <input id="title"/>
<button id="btn" type="button">Set</button>
<button type="button" id="btn2">选择文件</button>
文件绝对路径: <strong id="filePath"></strong>
<script src="./renderer.js"></script>
</body>
</html>render.js
javascript
const setButton = document.getElementById('btn')
const titleInput = document.getElementById('title')
setButton.addEventListener('click', () => {
const title = titleInput.value
window.electronAPI.setTitle(title)
})
const btn = document.getElementById('btn2')
btn.addEventListener('click', async () => {
const filePath = await window.electronAPI.openFile()
document.getElementById('filePath').innerText = filePath
})
window.electronAPI.handleCounter((event, value) => {
const oldValue = Number(counter.innerText)
const newValue = oldValue + value
counter.innerText = newValue
event.sender.send('counter-value', newValue)
})