Electron 项目中使用进程通信的几种方式

在使用 Vite + TS + Vue + Electron 搭建的项目中,使用进程通信,具有以下几种方式

使用预加载脚本

主进程需要开启进程隔离

electron/main.ts

dart 复制代码
import { app, BrowserWindow, ipcMain } from 'electron'
import { resolve } from 'path'

/* 
  在当前文件中你可以引入所有的主进程代码
  一个 Electron 应用只能有一个主进程,但可以多个渲染进程,一个 BrowserWindow 实例代表着一个渲染进程
  app:代表整个应用,可以获取应用程序生命周期的各个事件
  webContents:负责渲染和控制页面
  主进程:负责管理所有窗口及其对应的渲染进程,每个渲染进程都是独立的

  进程通信:
  主进程:ipcMain
  渲染进程:ipcRender
*/

let win: BrowserWindow | null

// 创建窗口
const createWindow = () => {
  // 创建浏览窗口
  win = new BrowserWindow({
    title: 'Main window',
    // 置于窗口之上
    alwaysOnTop: false,
    // 窗口位置及大小
    x: 1200,
    y: 10,
    width: 400,
    height: 300,
    // 是否允许改变窗口大小
    // resizable: true,
    // 是否显示窗口标题栏和边框,默认为 true
    frame: false,
    show: false,
    webPreferences: {
      // 集成 Node 环境
      // 如果加载一个不可信任的网页,应设置为 false,防止此页面有恶意脚本拥有访问 Node 环境的能力,做出伤害系统的行为
      nodeIntegration: true,
      // 开启进程隔离
      // 使用预加载脚本时,需要设置为 true,使用@vueuse/electron 或者 vite-plugin-electron-renderer 或者 remote 模块时,设置为 false
      // 默认为 true
      contextIsolation: true,
      // 网页的同源策略,关闭后,可以调用第三方网站的服务端接口,不会出现跨域问题
      // webSecurity: false,
      // 预加载脚本
      preload: resolve(__dirname, 'preload.js'),
    },
  })

  // 加载页面
  // You can use `process.env.VITE_DEV_SERVER_URL` when the vite command is called `serve`
  if (process.env.VITE_DEV_SERVER_URL) {
    win.loadURL(process.env.VITE_DEV_SERVER_URL)
  } else {
    // Load your file
    win.loadFile('dist/index.html')
  }

  // 打开开发工具
  // win.webContents.openDevTools()

  // 关闭控制台警告
  process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = 'true'

  win.once('ready-to-show', () => {
    win?.show()
  })

  win.on('closed', () => {
    win = null
  })
}

// 禁用当前应用程序的硬件加速,在 ready 之前调用
app.disableHardwareAcceleration()

// 这段程序将会在 Electron 结束初始化
// 和创建浏览器窗口的时候调用
// 部分 API 在 ready 事件触发后才能使用。
app.whenReady().then(() => {
  createWindow()

  app.on('activate', () => {
    // 在 macOS 系统内, 如果没有已开启的应用窗口
    // 点击托盘图标时通常会重新创建一个新窗口
    if (BrowserWindow.getAllWindows().length === 0) createWindow()
  })
})

// 除了 macOS 外,当所有窗口都被关闭的时候退出程序。 因此, 通常
// 对应用程序和它们的菜单栏来说应该时刻保持激活状态,
// 直到用户使用 Cmd + Q 明确退出
app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') app.quit()
})

ipcMain.on('window-min', () => {
  // 窗口最小化
  win?.minimize()
})

ipcMain.on('window-max', () => {
  // 窗口最大化
  const flag = win?.isMaximized()
  if (flag) return win?.unmaximize()

  win?.maximize()
})

ipcMain.on('window-close', () => {
  // 窗口关闭
  win?.close()
})

预加载脚本中使用 contextBridge 方法暴露相关 api 到渲染进程中

electron/preload.ts

arduino 复制代码
import { contextBridge, ipcRenderer } from 'electron'

/* 窗口操作 */
// 最小化
const min = () => {
  ipcRenderer.send('window-min')
}

// 最大化
const max = () => {
  ipcRenderer.send('window-max')
}

// 关闭
const close = () => {
  ipcRenderer.send('window-close')
}

contextBridge.exposeInMainWorld('electronAPI', {
  min,
  max,
  close,
})

渲染进程

xxx.vue

xml 复制代码
<script setup lang="ts">
  const { electronAPI } = window

  const min = () => {
    electronAPI.min()
  }

  const max = () => {
    electronAPI.max()
  }

  const close = () => {
    electronAPI.close()
  }
</script>

项目中集成 TS

global.d.ts

typescript 复制代码
export interface IElectronAPI {
  min:Function
  max:Function
  close:Function
}

declare global {
  interface Window {
    electronAPI: IElectronAPI
  }
}

@vueuse/electron

@vueuse/electron

主进程关闭进程隔离

electron/main.ts

yaml 复制代码
webPreferences: {
  ...
  // 关闭进程隔离
  contextIsolation: false,
  ...
}

渲染进程

xxx.vue

xml 复制代码
<script setup lang="ts">
  import { useIpcRenderer } from '@vueuse/electron'
  const ipcRenderer = useIpcRenderer()

  const min = () => {
    ipcRenderer.send('window-min')
  }

  const max = () => {
    ipcRenderer.send('window-max')
  }

  const close = () => {
    ipcRenderer.send('window-close')
  }
</script>

vite-plugin-electron-renderer

www.npmjs.com/package/vit...

需要在 vite.config.ts中进行配置,这样就可以在渲染进程中使用相关 api 了

vite.config.ts

javascript 复制代码
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import electron from 'vite-plugin-electron'
import renderer from 'vite-plugin-electron-renderer'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    vue(),
    electron(
      {
        entry: 'electron/main.ts',
        onstart: (options) => {
          options.startup()
        },
      }  
    ),
    // 在渲染进程中使用 electron api
    renderer(),
  ],
})

主进程需要关闭进程隔离

electron/main.ts

arduino 复制代码
webPreferences: {
  // 集成 Node 环境
  // 如果加载一个不可信任的网页,应设置为 false,防止此页面有恶意脚本拥有访问 Node 环境的能力,做出伤害系统的行为
  nodeIntegration: true,
  // 开启进程隔离
  contextIsolation: false,
  // 预加载脚本
  preload: resolve(__dirname, 'preload.js'),
}

渲染进程

xxx.vue

xml 复制代码
<script setup lang="ts">
  import { ipcRenderer } from 'electron'

  const min = () => {
    ipcRenderer.send('window-min')
  }

  const max = () => {
    ipcRenderer.send('window-max')
  }

  const close = () => {
    ipcRenderer.send('window-close')
  }
</script>

remote 模块

www.npmjs.com/package/@el...

需要在主进程中进行初始化,然后就可以在渲染进程中使用主进程的对象了

electron/main.ts

javascript 复制代码
import remote from '@electron/remote/main'

let win: BrowserWindow | null = null

app.whenReady().then(() => {
  createWindow()

  remote.initialize()
  remote.enable(win!.webContents)

})

渲染进程

xxx.vue

xml 复制代码
<script setup lang="ts">
  import { app, shell, getCurrentWindow } from '@electron/remote'
  const win = getCurrentWindow()

  const min = () => {
    win.minimize()
  }

  const max = () => {
    win.maximize()
  }

  const close = () => {
    win.close()
  }
</script>
相关推荐
王解34 分钟前
webpack loader全解析,从入门到精通(10)
前端·webpack·node.js
我不当帕鲁谁当帕鲁38 分钟前
arcgis for js实现FeatureLayer图层弹窗展示所有field字段
前端·javascript·arcgis
那一抹阳光多灿烂43 分钟前
工程化实战内功修炼测试题
前端·javascript
放逐者-保持本心,方可放逐2 小时前
微信小程序=》基础=》常见问题=》性能总结
前端·微信小程序·小程序·前端框架
毋若成4 小时前
前端三大组件之CSS,三大选择器,游戏网页仿写
前端·css
红中马喽4 小时前
JS学习日记(webAPI—DOM)
开发语言·前端·javascript·笔记·vscode·学习
Black蜡笔小新5 小时前
网页直播/点播播放器EasyPlayer.js播放器OffscreenCanvas这个特性是否需要特殊的环境和硬件支持
前端·javascript·html
秦jh_6 小时前
【Linux】多线程(概念,控制)
linux·运维·前端
蜗牛快跑2136 小时前
面向对象编程 vs 函数式编程
前端·函数式编程·面向对象编程
Dread_lxy6 小时前
vue 依赖注入(Provide、Inject )和混入(mixins)
前端·javascript·vue.js