• electron之进程间通信


    Electron进程间通信

    使用electron编写程序时经常遇到下面这种场景:
    当用户点击一个按钮时,需要将页面输入的信息保存到本地电脑上;
    或者是点击菜单时,需要页面窗口做出响应。
    用户点击的按钮和窗口展示的内容是运行在渲染进程中,而保存的操作和点击菜单是运行在主进程中的,渲染进程和主进程无法直接通信,
    这是就需要使用到进程间通信(IPC)

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

    渲染进程到主进程的通信

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

    main.js

    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()
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    preload.js

    const { contextBridge, ipcRenderer } = require('electron')
    
    contextBridge.exposeInMainWorld('myAPI', {
        saveText: (text) => ipcRenderer.invoke('save-text', text),
        queryText: () => ipcRenderer.invoke('query-text'),
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    index.html

    DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Titletitle>
    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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    运行结果如下:
    输入hello world!,点击保存,然后点击读取按钮,就会把保存的文件内容展示出来。
    在这里插入图片描述

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

    主进程到渲染进程的通信

    我们在窗口添加一个设置菜单和两个子菜单+1,-1,
    点击子菜单时页面数字做出相应反馈。
    main.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()
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    preload.js

    
    const { contextBridge, ipcRenderer } = require('electron')
    
    contextBridge.exposeInMainWorld('myAPI', {
        // 渲染进程监听update-counter事件
        handleCounter: (callback) => ipcRenderer.on('update-counter', callback)
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    index.html

    DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Titletitle>
    head>
    <body>
      <div>count:<span id="count">0span>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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    运行结果如下
    在这里插入图片描述

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

  • 相关阅读:
    python趣味编程-5分钟实现一个贪吃蛇游戏(含源码、步骤讲解)
    C/C++语言100题练习计划 92——矩阵加法(线性代数)
    mybatis用拦截器实现字段加解密
    代码随想录算法训练营Day32 | 贪心算法(2/6) Leetcode 122.买卖股票的最佳时机 II 55. 跳跃游戏 45.跳跃游戏II
    工程伦理--9.5 职业能力
    22个每个程序员都应该知道的 Git 命令
    Spring Authorization Server优化篇:Redis值序列化器添加Jackson Mixin,解决Redis反序列化失败问题
    Java 深度优先搜索 and 广度优先搜索的算法原理和代码展示
    WeNet:面向工业落地的E2E语音识别工具
    c单元语言测试--自定义代码、rspec 和Google test
  • 原文地址:https://blog.csdn.net/BDawn/article/details/133686459