likes
comments
collection
share

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

作者站长头像
站长
· 阅读数 22

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

使用预加载脚本

主进程需要开启进程隔离

electron/main.ts

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

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

<script setup lang="ts">
  const { electronAPI } = window

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

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

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

项目中集成 TS

global.d.ts

export interface IElectronAPI {
  min:Function
  max:Function
  close:Function
}

declare global {
  interface Window {
    electronAPI: IElectronAPI
  }
}

@vueuse/electron

@vueuse/electron

主进程关闭进程隔离

electron/main.ts

webPreferences: {
  ...
  // 关闭进程隔离
  contextIsolation: false,
  ...
}

渲染进程

xxx.vue

<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

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

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

渲染进程

xxx.vue

<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

import remote from '@electron/remote/main'

let win: BrowserWindow | null = null

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

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

})

渲染进程

xxx.vue

<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>
转载自:https://juejin.cn/post/7273096710825443380
评论
请登录