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计算机入门到高级架构师开发资料超级大礼包免费送!

相关推荐
EricWang135821 分钟前
[OS] 项目三-2-proc.c: exit(int status)
服务器·c语言·前端
September_ning21 分钟前
React.lazy() 懒加载
前端·react.js·前端框架
web行路人31 分钟前
React中类组件和函数组件的理解和区别
前端·javascript·react.js·前端框架
番茄小酱00132 分钟前
Expo|ReactNative 中实现扫描二维码功能
javascript·react native·react.js
子非鱼9211 小时前
【Ajax】跨域
javascript·ajax·cors·jsonp
超雄代码狂1 小时前
ajax关于axios库的运用小案例
前端·javascript·ajax
长弓三石1 小时前
鸿蒙网络编程系列44-仓颉版HttpRequest上传文件示例
前端·网络·华为·harmonyos·鸿蒙
小马哥编程1 小时前
【前端基础】CSS基础
前端·css
嚣张农民1 小时前
推荐3个实用的760°全景框架
前端·vue.js·程序员
周亚鑫2 小时前
vue3 pdf base64转成文件流打开
前端·javascript·pdf