Electron:构建跨平台桌面应用的现代方法

环境搭建与Hello World

main.js (主进程)

javascript 复制代码
const { app, BrowserWindow } = require('electron')

function createWindow () {
  // 创建一个新的浏览器窗口
  const mainWindow = new BrowserWindow({
    width: 800, // 窗口宽度
    height: 600, // 窗口高度
    webPreferences: {
      nodeIntegration: true, // 允许Node.js集成
      contextIsolation: false, // 如果使用了contextBridge,则应设为true
      enableRemoteModule: true // 是否启用remote模块
    }
  })

  // 加载index.html文件
  mainWindow.loadFile('index.html')

  // 打开开发者工具
  // mainWindow.webContents.openDevTools()
}

// 当Electron完成初始化并准备好创建浏览器窗口时调用此方法
app.whenReady().then(() => {
  createWindow()

  app.on('activate', function () {
    // 在macOS上,当点击dock图标并且没有其他窗口打开时,
    // 通常在应用程序中重新创建一个窗口。
    if (BrowserWindow.getAllWindows().length === 0) createWindow()
  })
})

// 关闭所有窗口时退出应用
app.on('window-all-closed', function () {
  // 在macOS上,除非用户按下Cmd + Q明确退出,
  // 否则应用程序及其菜单栏将保留在后台。
  if (process.platform !== 'darwin') app.quit()
})

index.html (渲染进程)

html 复制代码
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Hello World!</title>
  <!-- 引入样式 -->
  <link rel="stylesheet" href="styles.css">
</head>
<body>
  <h1>Hello World!</h1>
  <script>
    // 这里可以写渲染进程的JavaScript代码
    console.log('This is from renderer process.');
  </script>
</body>
</html>

styles.css (样式)

css 复制代码
body {
  margin: 0;
  padding: 0;
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  font-family: Arial, sans-serif;
  background-color: #f0f0f0;
}
h1 {
  color: #333;
}

主进程与渲染进程通信示例

假设我们要从渲染进程发送一条消息给主进程,并由主进程处理后回复。

main.js 添加以下代码:

javascript 复制代码
const { ipcMain } = require('electron')

// 监听来自渲染进程的消息
ipcMain.on('asynchronous-message', (event, arg) => {
  console.log(arg) // 打印接收到的消息
  event.sender.send('asynchronous-reply', 'pong') // 回复消息给渲染进程
})
index.html 中的JavaScript部分添加:

javascript
const { ipcRenderer } = require('electron')

document.getElementById('sendBtn').addEventListener('click', () => {
  ipcRenderer.send('asynchronous-message', 'ping') // 发送消息给主进程
})

// 监听主进程的回复
ipcRenderer.on('asynchronous-reply', (event, arg) => {
  console.log(arg) // 打印接收到的回复
})

窗口管理与菜单

窗口管理示例

创建新窗口

在main.js中,可以定义一个函数来创建新的窗口:

javascript 复制代码
function createNewWindow() {
  const newWindow = new BrowserWindow({
    width: 400,
    height: 300,
    webPreferences: {
      nodeIntegration: true,
      contextIsolation: false,
      enableRemoteModule: true
    }
  })
  newWindow.loadFile('newWindow.html')
}

并在某个事件中调用这个函数,比如在主窗口中点击按钮触发新窗口的创建。

菜单示例

创建一个简单的菜单:

main.js

javascript 复制代码
const { Menu } = require('electron')

const template = [
  {
    label: 'File',
    submenu: [
      {
        label: 'Open',
        accelerator: 'CmdOrCtrl+O',
        click() { /* 执行打开文件的逻辑 */ }
      },
      {
        label: 'Save',
        accelerator: 'CmdOrCtrl+S',
        click() { /* 执行保存文件的逻辑 */ }
      },
      { type: 'separator' },
      { role: 'quit' }
    ]
  },
  // 其他菜单项...
]

const menu = Menu.buildFromTemplate(template)
Menu.setApplicationMenu(menu)

文件系统操作

读取文件示例

javascript 复制代码
const fs = require('fs')

fs.readFile('path/to/your/file.txt', 'utf8', (err, data) => {
  if (err) {
    console.error(err)
    return
  }
  console.log(data)
})

保存文件示例

javascript 复制代码
fs.writeFile('path/to/your/newfile.txt', 'Hello Electron!', err => {
  if (err) throw err
  console.log('The file has been saved!')
})

打包与分发

使用electron-builder进行打包:

首先安装electron-builder

bash 复制代码
npm install --save-dev electron-builder

然后在package.json中配置打包信息:

json 复制代码
{
  "name": "your-app-name",
  "version": "1.0.0",
  "build": {
    "appId": "com.yourcompany.yourapp",
    "mac": {
      "category": "public.app-category.developer-tools"
    },
    "win": {
      "target": ["nsis"]
    }
  }
}

最后,运行打包命令:

bash 复制代码
# 打包为macOS应用
npm run build -- -m

# 打包为Windows应用
npm run build -- -w

自动更新

首先,安装electron-updater

bash 复制代码
npm install --save-dev electron-updater

在main.js中引入并配置自动更新:

javascript 复制代码
const { autoUpdater } = require('electron-updater')

autoUpdater.checkForUpdatesAndNotify()

autoUpdater.on('update-available', () => {
  dialog.showMessageBox({
    title: 'Update available',
    message: 'A new version is available. It will be downloaded in the background.'
  })
})

autoUpdater.on('update-downloaded', () => {
  dialog.showMessageBox({
    title: 'Update ready',
    message: 'The update has been downloaded. It will be installed on restart.'
  }).then(() => {
    autoUpdater.quitAndInstall()
  })
})

2500G计算机入门到高级架构师开发资料超级大礼包免费送!

相关推荐
致博软件F2BPM5 分钟前
Element Plus和Ant Design Vue深度对比分析与选型指南
前端·javascript·vue.js
慧一居士1 小时前
flex 布局完整功能介绍和示例演示
前端
DoraBigHead1 小时前
小哆啦解题记——两数失踪事件
前端·算法·面试
一斤代码6 小时前
vue3 下载图片(标签内容可转图)
前端·javascript·vue
中微子6 小时前
React Router 源码深度剖析解决面试中的深层次问题
前端·react.js
光影少年7 小时前
从前端转go开发的学习路线
前端·学习·golang
中微子7 小时前
React Router 面试指南:从基础到实战
前端·react.js·前端框架
3Katrina7 小时前
深入理解 useLayoutEffect:解决 UI "闪烁"问题的利器
前端·javascript·面试
前端_学习之路8 小时前
React--Fiber 架构
前端·react.js·架构
coderlin_8 小时前
BI布局拖拽 (1) 深入react-gird-layout源码
android·javascript·react.js