electron之进程间通信

Electron进程间通信

使用electron编写程序时经常遇到下面这种场景:

当用户点击一个按钮时,需要将页面输入的信息保存到本地电脑上;

或者是点击菜单时,需要页面窗口做出响应。

用户点击的按钮和窗口展示的内容是运行在渲染进程中,而保存的操作和点击菜单是运行在主进程中的,渲染进程和主进程无法直接通信,

这是就需要使用到进程间通信(IPC)

为了实现这种通信,Electron提供了 ipcMainipcRenderer 模块。

渲染进程到主进程的通信

下面是一个简单的例子,介绍在页面输入文本信息,然后点击按钮将文本信息保存到本地电脑,然后点击查询,读取本地电脑文件并将读取的文本展示出来。

main.js

javascript 复制代码
const { app, BrowserWindow, ipcMain } = require('electron')
const {join} = require("path");
const fs = require("fs");

// 应用创建窗口
const createWindow = () => {
    const win = new BrowserWindow({
        width: 800,
        height: 600,
        webPreferences: {
            preload: join(__dirname, 'preload.js')
        }
    })
    win.loadFile('index.html')
    win.webContents.openDevTools();
}
app.whenReady().then(() => {
    // 处理保存文本的事件
    ipcMain.handle('save-text', async (event, text) => {
        const filePath = `./output.txt`;
        fs.writeFileSync(filePath, text);
    });

    // 处理查询文本的事件
    ipcMain.handle('query-text', async (event) => {
        const filePath = `./output.txt`;
        return fs.readFileSync(filePath, {encoding: 'utf-8'});
    });
    createWindow()
})

preload.js

js 复制代码
const { contextBridge, ipcRenderer } = require('electron')

contextBridge.exposeInMainWorld('myAPI', {
    saveText: (text) => ipcRenderer.invoke('save-text', text),
    queryText: () => ipcRenderer.invoke('query-text'),
})

index.html

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
  <label>
      输入文本信息:
      <input id="input-name" type="text">
  </label>
  <input id="save" type="button" value="保存">
  <div>
      <input id="query" type="button" value="读取文本信息">
      <div id="text"></div>
  </div>

<script>
    const saveButton = document.getElementById('save')
    saveButton.addEventListener('click', () => {
        const inputName = document.getElementById('input-name')
        window.myAPI.saveText(inputName.value)
    })

    const queryButton = document.getElementById('query')
    queryButton.addEventListener('click', async () => {
        const text = document.getElementById('text')
        text.innerHTML = await window.myAPI.queryText()
    })

</script>
</body>
</html>

运行结果如下:

输入hello world!,点击保存,然后点击读取按钮,就会把保存的文件内容展示出来。

这个是渲染进程到主进程的通信,下面介绍一下主进程到渲染进程的通信。

主进程到渲染进程的通信

我们在窗口添加一个设置菜单和两个子菜单+1,-1,

点击子菜单时页面数字做出相应反馈。

main.js

js 复制代码
const { app, BrowserWindow, Menu } = require('electron')
const {join} = require("path");

// 应用创建窗口
const createWindow = () => {
    const win = new BrowserWindow({
        width: 800,
        height: 600,
        webPreferences: {
            preload: join(__dirname, 'preload.js')
        }
    })
    // 设置窗口菜单
    const menu = Menu.buildFromTemplate([
        {
            label: '设置',
            submenu: [
                {
                    // 点击+1按钮时触发update-counter事件并传递参数1
                    click: () => win.webContents.send('update-counter', 1),
                    label: '+1'
                },
                {
                    // 点击-1按钮时触发update-counter事件并传递参数-1
                    click: () => win.webContents.send('update-counter', -1),
                    label: '-1'
                }
            ]
        }
    ])

    Menu.setApplicationMenu(menu)
    win.loadFile('index.html')
    win.webContents.openDevTools();
}
app.whenReady().then(() => {
    createWindow()
})

preload.js

js 复制代码
const { contextBridge, ipcRenderer } = require('electron')

contextBridge.exposeInMainWorld('myAPI', {
    // 渲染进程监听update-counter事件
    handleCounter: (callback) => ipcRenderer.on('update-counter', callback)
})

index.html

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
  <div>count:<span id="count">0</span></div>

<script>
    const count = document.getElementById('count')
    // 传入监听update-counter事件的回调函数
    window.myAPI.handleCounter((event, value) => {
        const num = Number(count.innerText)
        count.innerText = num + value
    })

</script>
</body>
</html>

运行结果如下

以上就是electron的进程间通信,欢迎大家在评论区留言指正,相互学习

相关推荐
练习两年半的工程师28 分钟前
使用React和google gemini api 打造一个google gemini应用
javascript·人工智能·react.js
勘察加熊人1 小时前
angular九宫格ui
javascript·ui·angular.js
姑苏洛言2 小时前
30天搭建消防安全培训小程序
前端
左钦杨3 小时前
Nuxt2 vue 给特定的页面 body 设置 background 不影响其他页面
前端·javascript·vue.js
yechaoa3 小时前
【揭秘大厂】技术专项落地全流程
android·前端·后端
MurphyChen3 小时前
🤯 一行代码,优雅的终结 React Context 嵌套地狱!
前端·react.js
逛逛GitHub4 小时前
推荐 10 个受欢迎的 OCR 开源项目
前端·后端·github
_xaboy4 小时前
开源 FormCreate 表单设计器配置组件的多语言
前端·vue.js·低代码·开源·可视化表单设计器
uglyduckling04124 小时前
小程序构建NPM失败
前端·小程序·npm
草原上唱山歌4 小时前
C/C++都有哪些开源的Web框架?
前端·c++·开源