最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • electron中的ipc通信(三)

    正文概述 掘金(_aymfx)   2021-01-12   816

    上次写了关于ipc通讯的一些方式,主要都是web页面向主进程通讯,主进程回复通讯,这个感觉和http有点相似,发送一个http资源的请求,服务返回一个资源结果,现在我们主要看这两个点

    • 主进程主动推消息给web渲染进程的
    • web渲染进程之间的通讯

    主进程向渲染进程主动通信

    const { BrowserWindow } = require('electron')
    const win = new BrowserWindow({ width: 800, height: 600 })
    win.loadURL('http://github.com')
    const contents = win.webContents
    console.log(contents)
    

    这个创建之后返回的win下面的webContents就是可以渲染和控制web页面的api模块,咱们不会深入展开的,主要针对通讯讲一讲

    contents.send(channel, ...args)

    • channel String 事件名称
    • ...args any[] 传递的参数,和上节一样

    目录准备,修改和删除都在这几个文件操作

    my-electron-app/
    ├── package.json  
    ├── main.js // 这个就是主进程
    ├── renderer.js // 这个就是渲染进程
    └── index.html //web页面
    

    index.html

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Electron演示</title>
    </head>
    
    <body>
        Electron演示
        <iframe src='./other.html'></iframe>
        <script src="./renderer.js"></script>
    </body>
    
    </html>
    

    renderer.js

    const { ipcRenderer } = require("electron");
    
    ipcRenderer.on("message", (event, arg) => {
      console.log("主进程老哥,主动推消息了:", arg);
    });
    

    main.js

    const { app, BrowserWindow, ipcMain } = require("electron");
    function createWindow() {
      const win = new BrowserWindow({
        width: 1920,
        height: 1080,
        webPreferences: {
          nodeIntegration: true,
          contextIsolation: false,
        },
      });
      const contents = win.webContents;
      contents.openDevTools(); //打开调试工具
      win.loadFile("index.html");
      contents.on("did-finish-load", () => {
        //页面加载完成触发的回调函数
        console.log("load");
        contents.send("message", "我看到你加载完了,给你发个信息");
      });
    }
    
    app.whenReady().then(createWindow);
    
    app.on("window-all-closed", () => {
      if (process.platform !== "darwin") {
        app.quit();
      }
    });
    
    app.on("activate", () => {
      if (BrowserWindow.getAllWindows().length === 0) {
        createWindow();
      }
    });
    
    

    electron中的ipc通信(三)

    contents.sendToFrame(frameId, channel, ...args) 通过frameId给渲染进程中嵌入的webview发送消息

    • frameId Integer | [number, number]
    • channel String
    • ...args any[]

    首先如何拿到框架的id?

    第一种渲染进程主动调用方法去拿到id,然后调用取方法

    console.log('My frameId is:', require('electron').webFrame.routingId) //然后你把这个传给主进程
    

    第二种主进程通过监听的函数去拿,因为渲染进程发消息会触发主进程的事件,我们就可以通过event去拿

    ipcMain.on('ping', (event) => {
      console.info('Message came from frameId:', event.frameId)
    })
    

    index.html

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Electron演示</title>
    </head>
    
    <body>
        Electron演示
        <webview src='./other.html' webpreferences="nodeIntegration=true"></webview> //具体查api
        <script src="./renderer.js"></script>
    </body>
    
    </html>
    

    main.js

    const { app, BrowserWindow, ipcMain } = require("electron");
    let win;
    function createWindow() {
      win = new BrowserWindow({
        width: 1920,
        height: 1080,
        webPreferences: {
          nodeIntegration: true,
          webviewTag: true, //需要设置webview来启用这个
        },
      });
      const contents = win.webContents;
      contents.openDevTools(); //打开调试工具
      win.loadFile("index.html");
      contents.on("did-finish-load", () => {
        //页面加载完成触发的回调函数
        console.log("load");
        // contents.send("message", "我看到你加载完了,给你发个信息");
      });
    }
    
    ipcMain.on("getFrameId", (event, arg) => {
      console.log("收到了FrameId", arg); //收到了FrameId 1
      console.log("event收到了FrameId", event.frameId); //event收到了FrameId 1
      win.webContents.sendToFrame(
        event.frameId,
        "message",
        "我看到你加载完了,给你发个信息"
      );
    });
    
    app.whenReady().then(createWindow);
    app.on("window-all-closed", () => {
      if (process.platform !== "darwin") {
        app.quit();
      }
    });
    
    app.on("activate", () => {
      if (BrowserWindow.getAllWindows().length === 0) {
        createWindow();
      }
    });
    
    

    other.html

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>其他页面</title>
    </head>
    
    <body>
        <script>
            const {
                ipcRenderer,
                webFrame
            } = require("electron");
            ipcRenderer.send("getFrameId", webFrame.routingId);
            ipcRenderer.on("message", (event, arg) => {
                console.log("(renderer2)主进程老哥,主动推消息了:", arg);
            });
        </script>
    </body>
    
    </html>
    

    renderer.js

    const { ipcRenderer, webFrame } = require("electron");
    console.log("My frameId is:", webFrame.routingId);
    
    ipcRenderer.on("message", (event, arg) => {
      console.log("(renderer2)主进程老哥,主动推消息了:", arg);
    });
    

    结果

    electron中的ipc通信(三)

    electron中的ipc通信(三)

    contents.postMessage(channel, message, [transfer]) 利用原生的webworker进行通讯

    • channel String
    • message any
    • transfer MessagePortMain[] (optional)

    只写关键性代码,具体的代码参看最上面的改动,对照一下

    main.js

    contents.on("did-finish-load", () => {
        const { port1, port2 } = new MessageChannelMain();
        contents.postMessage("message", "我看到你加载完了,给你发个信息", [port1]);
        port2.postMessage("再给你发个消息");
    });
    

    renderer.js

    ipcRenderer.on("message", (event, arg) => {
      const [port] = event.ports;
      console.log(arg, event);
      port.onmessage = (arg) => {
        console.log(arg.data);
      };
    });
    

    结果

    • 我看到你加载完了,给你发个信息 Object

    • 再给你发个消息

    以上就是借助 webContent功能模块 主进程向渲染进程通信

    渲染进程互相通信

    ipcRenderer.sendTo(webContentsId, channel, ...args)

    • webContentsId Number 渲染进程的id
    • channel String
    • ...args any[]

    获取渲染进程的id

    • 可以在创建窗口的时候保存每个窗口的id
    • 或者创建一个主进程事件获取每个渲染进程的id

    main.js

    const { app, BrowserWindow, ipcMain } = require("electron");
    let win;
    let ids = {
      "index.html": null,
    };
    function createWindow() {
      win = new BrowserWindow({
        width: 1920,
        height: 1080,
        webPreferences: {
          nodeIntegration: true,
          contextIsolation: false,
          webviewTag: true, //需要设置webview来启用这个
        },
      });
      const contents = win.webContents;
      contents.openDevTools(); //打开调试工具
      win.loadFile("index.html");
      ids["index.html"] = contents.id;
    }
    
    ipcMain.on("registerFrameId", (event, arg) => {
      console.log(arg);
      ids = Object.assign(ids, arg);
    });
    
    ipcMain.on("getFrameId", (event, arg) => {
      event.returnValue = ids[arg];
    });
    
    app.whenReady().then(createWindow);
    app.on("window-all-closed", () => {
      if (process.platform !== "darwin") {
        app.quit();
      }
    });
    
    app.on("activate", () => {
      if (BrowserWindow.getAllWindows().length === 0) {
        createWindow();
      }
    });
    
    

    renderer.js

    const { ipcRenderer } = require("electron");
    
    onload = () => {
      const webview = document.querySelector("webview");
      webview.addEventListener("did-finish-load", () => {
        webview.openDevTools();
        let otherId = ipcRenderer.sendSync("getFrameId", "other.html");
        console.log(otherId);
        ipcRenderer.sendTo(otherId, "webview", "other老弟,喝一口");
      });
      ipcRenderer.on("webview", (event, arg) => {
        console.log("来自other.html消息:", arg);
      });
    };
    

    other.html

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>其他页面</title>
    </head>
    
    <body>
        <script>
            onload = () => {
                const {
                    ipcRenderer,
                    remote //从remote模块获取到窗体的唯一id
                } = require("electron");
                // let webContent = webContents.getFocusedWebContents()
                const webContent = remote.getCurrentWebContents();
                console.log(webContent.id)
                ipcRenderer.send("registerFrameId", {
                    'other.html': webContent.id
                });
                let indexId = ipcRenderer.sendSync('getFrameId', 'index.html')
                ipcRenderer.sendTo(indexId, "webview", "index老哥,给你发消息了");
                ipcRenderer.on("webview", (event, arg) => {
                    document.write("来自html.html消息:", arg)
                });
            }
        </script>
    </body>
    
    </html>
    

    Index.html

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Electron演示</title>
    </head>
    
    <body>
        Electron演示
        <webview src='./other.html' webpreferences="nodeIntegration=true" id="webview"></webview>
        <script src="./renderer.js"></script>
    </body>
    
    </html>
    

    结果

    electron中的ipc通信(三)

    ipcRenderer.sendToHost(channel, ...args)

    • channel String
    • ...args any[]

    就像 ipcRenderer.send,不同的是消息会被发送到 host 页面上的 <webview> 元素,而不是主进程

    需要用到webview的一个事件监听 'ipc-message' 监听发布的消息

    具体改动这个地方

    other.html

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>其他页面</title>
    </head>
    
    <body>
        asdada
        <script>
            const {
                ipcRenderer,
            } = require("electron");
            ipcRenderer.on('ping', (event, arg) => {
                console.log("来自主页面的回话", arg)
                ipcRenderer.sendToHost('message', '小哥我给你发信息了')
            })
        </script>
    </body>
    </html>
    

    renderer.js

    onload = () => {
      const webview = document.querySelector("webview");
      webview.addEventListener("ipc-message", (event) => {
        console.log("来自webview的回话:", event);
      });
      webview.addEventListener("did-finish-load", () => {
        webview.openDevTools();
        webview.send("ping", "理我一下");
      });
    };
    

    结果

    electron中的ipc通信(三)

    如果觉得我的文章还可以,点个赞或者关注一下下,还有精彩的故事等着你哦,还可以云撸猫


    起源地下载网 » electron中的ipc通信(三)

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元