zoukankan      html  css  js  c++  java
  • 02.electron in action(note): chapter03 -主进程与渲染进程

    主进程和渲染进程

    在electron中,GUI的相关的模块仅在主进程中可用

    若渲染进程要完成GUI操作,有两种方式:

    • 渲染进程向主进程发送消息,让主进程完成相应的操作
    • 通过渲染进程的remote模块完成相应的操作

    调试主进程

    在VSC中,点击左侧的菜单栏的 debug图标,添加launch.json, 添加配置Node.js Electron 主程序

    image-20200608170045910

    自动生成如下配置:

    {
        // 使用 IntelliSense 了解相关属性。 
        // 悬停以查看现有属性的描述。
        // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
        "version": "0.2.0",
        "configurations": [
            
    
            {
                "type": "node",
                "request": "launch",
                "name": "Electron Main",
                "runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron",
                "program": "${workspaceFolder}/main.js",
                "skipFiles": [
                    "<node_internals>/**"
                ]
            }
            
        ]
    }
    
     在主进程`main.js`中打个断点, 按下快捷键 F5,即可进行调试
    

    调试渲染进程

    使用Chrome浏览器的开发者工具, 快捷方式 Ctrl + Shift + I
    

    进程互访

    remote

    渲染进行访问主进程对象

    remote`对象的属性和方法(包括类型的构造函数) 都是主进程的属性和方法的映射。

    index.html

          <script>
                    require('./index.js')
            </script>
    

    index.js

    let { remote } = require('electron');
    remote.getCurrentWindow().webContents.openDevTools();
    

    渲染进程访问主进程自定义内容

    • 创建一个Model

      mainModel.js

      let { BrowserWindow } = require('electron')
      exports.makeWin = function () { 
          let win = new BrowserWindow({
              webPreferences: {
                  nodeIntegration: true
              }
          });
          return win;
      }
      
    • index.htmlindex.js

      <!DOCTYPE html>
      <html>
      <head>
          <title>窗口标题</title>
      </head>
      <body>
          <h1>Hello World!</h1>
          <div>
              <button id="btn-make-win">创建窗口</button>
          </div>
          <script>
              require('./index.js')
          </script>
      </body>
      </html>
      
      let { remote } = require('electron');
      let mainModel = remote.require('./mainModel');
      
      remote.getCurrentWindow().webContents.openDevTools();
      let win2 = null;
      
      document.getElementById("btn-make-win").addEventListener('click', () => {
          win2 = mainModel.makeWin();
          win2.loadFile('index.html');
      })
      
      

      使用 remote.require加载 mainModel.js', makeWin将在主进程中运行。

      主进程访问渲染进程对象

      因为渲染进程是有主进程创建的,故主进程可以以直接访问渲染进程的对象和类型

    进程间消息传递

    渲染进程向主进程发送消息

    • index.html
          <button id="btn-ipc-renderer">渲染进程向主进程发送消息</button>
    
    • index.js

      let { ipcRenderer } = require('electron');
      document.getElementById("btn-ipc-renderer").addEventListener('click', () => {
          ipcRenderer.send('msg_renderer_to_main', { 'param1': "hello" }, { 'param2': "world" });
      })
      

      渲染进程使用 ipcRenderer.send()` 发送消息

    • main.js

      let { ipcMain} = require('electron');
      ...
      app.on('ready', () => {
          ...
          
          ipcMain.on("msg_renderer_to_main", (event, param1, param2) => { 
              console.log(param1);
              console.log(param2);
              console.log(event.sender);
          })
      });
      

      主机进程使用 ipcMain.on接收消息

    主进程向渲染进程发送消息

    • main.js

          ipcMain.on("msg_renderer_to_main", (event, param1, param2) => { 
              console.log(param1);
              console.log(param2);
              console.log(event.sender);
              
              //主进程向渲染进程发送消息:方式一
              event.sender.send("msg_main_to_renderer_bysend", { "arg1": "send" }, "msg from main by send!");
              //主进程向渲染进程发送消息:方式二
              event.reply("msg_main_to_renderer_byreply", { "reply-arg1": "reply" }, "msg from main by reply!");
             //主进程向渲染进程发送消息:方式三
              win.send("msg_main_to_renderer_byWindow", { "Window-arg1": "reply" }, "msg from main by Window!");
          })
      
      主线程使用`event.sender.send()`、`event.reply()`、`BrowseWindow.send()` 向渲染进程发送消息,
      

    其中 ,event.sender:代表发送消息的渲染进程的webContents

    特别注意
    无论使用event.sender.send还是event.reply
    只有event的发送者所在的渲染进程才收到消息, 如果使用win.send(),那么 只用win所在的在渲染进程才能收到消息

    • index.js
    ipcRenderer.on('msg_main_to_renderer_bysend', (event, param1, param2) => {
        console.log(param1);
        console.log(param2);
    });
    
    ipcRenderer.on('msg_main_to_renderer_byreply', (event, param1, param2) => {
        console.log(param1);
        console.log(param2);
    });
    
    ipcRenderer.on('msg_main_to_renderer_byWindow', (event, param1, param2) => {
        console.log(param1);
        console.log(param2);
    });
    

    渲染进程使用ipcRenderer.on()接收主线程的消息

    渲染进程间消息传递

    通过主进程中转

            窗口之间传递的消息,都先发到主进程,再由主进程转发
    

    通过窗口的webContents.id

    • index.html

          <button id="btn-send-msg-between-renderer">渲染进程间发送消息</button>
      
    • index.js

      let win2 = null;
      document.getElementById("btn-make-win").addEventListener('click', () => {
          win2 = mainModel.makeWin();
          win2.loadFile('index.html');
      })
      ...
      
      //渲染进程间直接发送消息
      document.getElementById("btn-send-msg-between-renderer").addEventListener('click', () => {
          console.log("msg_between_renderer");
          ipcRenderer.sendTo(win2.webContents.id, 'msg_renderer_to_renderer', { 'param1': "hello" }, { 'param2': "world" });
      });
      //接收渲染进程间消息
      ipcRenderer.on('msg_renderer_to_renderer', (event, param1, param2) => {
          console.log(param1);
          console.log(param2);
      });
      

    Remote模块的局限性

    • 性能消耗大

    • 制造混乱

    • 制造假象

    • 存在安全问题

  • 相关阅读:
    web应用模式
    Win10升级本地Django版本,以及DRF框架的安装使用
    DRF作业(1)
    中间件作业
    复习day03作业
    python基础复习
    利用自定义中间件来实现DRF框架中的request对象的data属性
    复习Day02(python中魔法方法,cookie/sesison/token,pymysql)
    排序之快排
    排序之归并
  • 原文地址:https://www.cnblogs.com/easy5weikai/p/13080974.html
Copyright © 2011-2022 走看看