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的进程间通信,欢迎大家在评论区留言指正,相互学习

相关推荐
战神刘玉栋8 分钟前
《基于 defineProperty 实现前端运行时变量检测》
前端
GISer_Jing17 分钟前
Javascript常见数据结构和设计模式
开发语言·javascript·数据结构
敲厉害的燕宝17 分钟前
【若依前后端分离】通过输入用户编号自动带出部门名称(部门树)
javascript·vue.js·elementui
嘻嘻哈哈1730 分钟前
vue安装+测试
前端·javascript·vue.js
大学生小郑36 分钟前
VUE与React的生命周期对比
前端·vue.js·react.js
JerryXZR41 分钟前
Angular基础保姆级教程 - 1
前端·javascript·angular.js
金灰42 分钟前
14-Django项目--文件上传-Excel
服务器·前端·javascript
inksci1 小时前
用 Echarts 画折线图
前端·javascript·html·echarts
子洋1 小时前
Leafer 开发小游戏 - 拼图
前端·游戏开发·canvas
JUANのWEB1 小时前
【WEB前端】---HTML---结构---笔记
前端·笔记·html