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

相关推荐
Smile_Gently2 小时前
前端:最简单封装nmp插件(组件)过程。
前端·javascript·vue.js·elementui·vue
nihui1237 小时前
Uniapp 实现顶部标签页切换功能?
javascript·vue.js·uni-app
luckycoke8 小时前
小程序立体轮播
前端·css·小程序
一 乐8 小时前
高校体育场管理系统系统|体育场管理系统小程序设计与实现(源码+数据库+文档)
前端·javascript·数据库·spring boot·高校体育馆系统
懒羊羊我小弟8 小时前
常用Webpack Loader汇总介绍
前端·webpack·node.js
shengmeshi9 小时前
vue3项目img标签动态设置src,提示:ReferenceError: require is not defined
javascript·vue.js·ecmascript
BillKu9 小时前
vue3中<el-table-column>状态的显示
javascript·vue.js·elementui
祈澈菇凉9 小时前
ES6模块的异步加载是如何实现的?
前端·javascript·es6
我爱学习_zwj9 小时前
4.从零开始学会Vue--{{组件通信}}
前端·javascript·vue.js·笔记·前端框架
顾比魁9 小时前
XSS盲打:当攻击者“盲狙”管理员
前端·网络安全·xss