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>
相关推荐
家里有只小肥猫20 分钟前
uniApp小程序保存canvas图片
前端·小程序·uni-app
前端大全22 分钟前
Chrome 推出全新的 DOM API,彻底革新 DOM 操作!
前端·chrome
八角丶34 分钟前
元素尺寸的获取方式及区别
前端·javascript·html
冴羽42 分钟前
Svelte 最新中文文档教程(16)—— Context(上下文)
前端·javascript·svelte
前端小臻1 小时前
关于css中bfc的理解
前端·css·bfc
白嫖不白嫖1 小时前
网页版的俄罗斯方块
前端·javascript·css
HappyAcmen1 小时前
关于Flutter前端面试题及其答案解析
前端·flutter
顾比魁1 小时前
pikachu之CSRF防御:给你的请求加上“网络身份证”
前端·网络·网络安全·csrf
林的快手1 小时前
CSS文本属性
前端·javascript·css·chrome·node.js·css3·html5
肥肠可耐的西西公主2 小时前
前端(AJAX)学习笔记(CLASS 2):图书管理案例以及图片上传
前端·笔记·学习