摘要:為了能使不同的進(jìn)程互相訪問資源并進(jìn)行協(xié)調(diào)工作,才有了進(jìn)程間通信。此時(shí),就需要與渲染進(jìn)程通信了。發(fā)消息,渲染進(jìn)程收消息內(nèi)部使用來發(fā)消息。
前言作者:鐘離,酷家樂PC客戶端負(fù)責(zé)人
原文地址:https://webfe.kujiale.com/electron-ku-jia-le-ke-hu-duan-kai-fa-shi-jian-fen-xiang-jin-cheng-tong-xin/
酷家樂客戶端:下載地址 https://www.kujiale.com/activity/136
文章背景:在酷家樂客戶端在V12改版成功后,我們積累了許多的寶貴的經(jīng)驗(yàn)和最佳實(shí)踐。前端社區(qū)里關(guān)于Electron知識(shí)相對(duì)較少,因此希望將這些內(nèi)容以系列文章的形式分享出來。
系列文章:【Electron】酷家樂客戶端開發(fā)實(shí)踐分享 — 入坑篇
【Electron】酷家樂客戶端開發(fā)實(shí)踐分享 — 軟件自動(dòng)更新
【Electron】酷家樂客戶端開發(fā)實(shí)踐分享 — 瀏覽器啟動(dòng)客戶端
【Electron】酷家樂客戶端開發(fā)實(shí)踐分享 — 進(jìn)程通信
【Electron】酷家樂客戶端開發(fā)實(shí)踐分享 — 下載管理器
不定期更新...
Electron中的進(jìn)程,其實(shí)就是計(jì)算機(jī)中的進(jìn)程,我們先來看看什么是進(jìn)程通信
進(jìn)程間通信(IPC,Inter-Process Communication),指至少兩個(gè)進(jìn)程或線程間傳送數(shù)據(jù)或信號(hào)的一些技術(shù)或方法
每個(gè)進(jìn)程都有自己的一部分獨(dú)立的系統(tǒng)資源,彼此是隔離的。為了能使不同的進(jìn)程互相訪問資源并進(jìn)行協(xié)調(diào)工作,才有了進(jìn)程間通信。
一個(gè)Electron應(yīng)用有一個(gè)主進(jìn)程和多個(gè)渲染進(jìn)程,渲染進(jìn)程還可能內(nèi)嵌多個(gè)webview。兩兩之間都可能需要進(jìn)行通信,情況還是比較復(fù)雜的。
需要通信的對(duì)象主進(jìn)程: 使用ipcMain進(jìn)行通信
渲染進(jìn)程: 使用ipcRenderer和remote模塊進(jìn)行通信
webview: 一般會(huì)禁用webview的node集成,然后使用preload的方式拿到ipcRenderer來做進(jìn)程通信。
// preload.js const electron = require("electron"); const { ipcRenderer } = electron; // 把ipcRenderer掛載到window上,webview內(nèi)部的js可以拿到這個(gè)模塊 window.ElectronIpcRenderer = ipcRenderer;ipcRenderer/ipcMain VS remote
主進(jìn)程和渲染進(jìn)程通信方式,擰出來多帶帶說一下。先來看一個(gè)簡(jiǎn)單例子的:
點(diǎn)擊創(chuàng)建按鈕,創(chuàng)建一個(gè)新的窗口。點(diǎn)擊關(guān)閉按鈕,關(guān)掉這個(gè)新窗口。
左側(cè)代碼使用ipcRenderer/ipcMain進(jìn)行通信,右側(cè)代碼使用remote進(jìn)行通信。實(shí)現(xiàn)的功能都是一樣的。從這個(gè)例子中可以發(fā)現(xiàn):
使用ipcMain/ipcRenderer通信,業(yè)務(wù)邏輯同時(shí)存在于主進(jìn)程和渲染進(jìn)程的代碼中。同時(shí)為了通信,會(huì)產(chǎn)生非常多的event & event handler。
使用remote通信,渲染進(jìn)程直接獲取主進(jìn)程模塊。而且,使用remote通信不需要使用事件和回調(diào)函數(shù),寫出來的代碼清晰直觀。
主進(jìn)程可以視作為模塊提供者,而渲染進(jìn)程是模塊的消費(fèi)者,渲染進(jìn)程通過remote來獲取主進(jìn)程的模塊,實(shí)現(xiàn)業(yè)務(wù)邏輯。這樣做有以下好處:
主進(jìn)程/渲染進(jìn)程代碼解耦,職責(zé)分明,提升可維護(hù)性
業(yè)務(wù)邏輯內(nèi)聚在渲染進(jìn)程
減少主進(jìn)程/渲染進(jìn)程冗余無用的代碼
具體實(shí)現(xiàn)介紹了一下前置知識(shí),現(xiàn)在來看看不同情況下,Electron進(jìn)程通信的實(shí)現(xiàn)方法。
主進(jìn)程和渲染進(jìn)程通信主進(jìn)程發(fā)消息、渲染進(jìn)程收消息:主進(jìn)程使用窗口的webContents發(fā)消息,渲染進(jìn)程內(nèi)使用ipcRenderer收消息
// main.js const win = new BrowserWindow(); win.load("index.html"); win.webContents.send("hello", {a: 1}); // index.html 中的js const { ipcRenderer } = require("electron"); ipcRenderer.on("hello", (e, data) => { console.log(data); // 打印出 {a: 1} })
渲染進(jìn)程發(fā)消息、主進(jìn)程收消息: 渲染進(jìn)程使用ipcRenderer發(fā)消息,主進(jìn)程使用ipcMain收消息。
// main.js const { ipcMain } = require("electron"); ipcMain.on("hello", (e, data) => { console.log(data); // 打印出 {a: 1} }); // index.html 中的js const { ipcRenderer } = require("electron"); ipcRenderer.send("hello", {a: 1});
一般遇到主進(jìn)程和渲染進(jìn)程通信的情況,大部分都是渲染進(jìn)程來需要獲取主進(jìn)程的模塊,此時(shí)推薦使用remote來做通信。
// main.js // 主進(jìn)程無需添加任何代碼 // index.html 中的js,獲取主進(jìn)程模塊 const { remote } = require("electron"); const {app, BrowserWindow, dialog, ...} = remote;渲染進(jìn)程與渲染進(jìn)程通信
渲染進(jìn)程之間也是會(huì)頻繁通信的,具體場(chǎng)景舉例:在設(shè)置窗口點(diǎn)擊更換皮膚,需要通知所有窗口進(jìn)行顏色、背景的更新。
最佳實(shí)踐:渲染進(jìn)程A通過remote模塊,獲取到需要目標(biāo)窗口的webContents對(duì)象,然后通過webContents向目標(biāo)窗口的發(fā)送消息。目標(biāo)窗口使用ipcRenderer監(jiān)聽事件。
const { remote } = require("electron") const allWindows = remote.BrowserWindow.getAllWindows(); // 窗口A中的邏輯 // 1、第一步,獲取到目標(biāo)窗口的webContents // 可以根據(jù)id,title來找到目標(biāo)窗口,也可以用其他辦法 const targetId = 1; const targetTitle = "目標(biāo)窗口"; // let targetWindow = allWindows.find(w => w.id === targetId); let targetWindow = allWindows.find(w => w.title === targetTitle); // 2、第二步,使用目標(biāo)窗口的webContents發(fā)送消息 targetWindow.webContents.send("theme-change", "gray"); // 目標(biāo)窗口內(nèi)的邏輯,使用ipcRenderer監(jiān)聽事件 // 窗口收到theme-change事件,改變窗口顏色。不需要關(guān)注事件從哪里發(fā)出,只需要關(guān)注接收到該事件后做什么 ipcRenderer.on("theme-change", (e, theme) => { console.log(theme); // gray });
還有一種傳統(tǒng)的辦法,不用remote,改用ipcMain做通信,但是會(huì)在主進(jìn)程冗余很多事件代碼。因此還是推薦使用remote,理由同上。小例子:
// mian.js // 用于事件轉(zhuǎn)發(fā),沒有實(shí)際的邏輯 ipcMain.on("send-event-to-window", (e, id, eventName, ...args) => { BrowserWindow.getAllWindows() .find(w = > w.id === id) .webContents .send(eventName, ...args); }); // 窗口A內(nèi)部,向主進(jìn)程發(fā)事件 const targetId = 1; ipcRenderer.send("send-event-to-window", id, "theme-change", "gray"); // 目標(biāo)窗口 ipcRenderer.on("theme-change", (e, theme) => { console.log(theme); // gray });webview與渲染進(jìn)程通信
內(nèi)嵌的web頁面運(yùn)行在客戶端中,也可以獲取本地化的能力。此時(shí),webview就需要與渲染進(jìn)程通信了。
在文章開頭講到了,為了應(yīng)用的安全性webview是需要禁用node集成的,通過preload的方式,注入了一個(gè)ipcRenderer并掛載到window上。
webview發(fā)消息,渲染進(jìn)程收消息:webview內(nèi)部使用ipcRenderer.sendToHost來發(fā)消息。渲染進(jìn)程獲取到webview的dom元素,監(jiān)聽dom元素的ipc-message事件接收消息
// 渲染進(jìn)程拿到webview的dom,接收事件 const webview = document.querySelector("webview") webview.addEventListener("ipc-message", (event) => { console.log(event.channel); // hello }); // webview頁面內(nèi),假裝點(diǎn)了一個(gè)按鈕,發(fā)送事件 btn.onclick = () => { window.ElectronIpcRenderer.sendToHost("hello") }
渲染進(jìn)程發(fā)消息,webview收消息:渲染進(jìn)程使用webview.send發(fā)消息。webview使用內(nèi)置的ipcRenderer收消息。
// webview內(nèi)部 window.ElectronIpcRenderer.on("event-from-renderer", (e, data) => { console.log(e, data); // {a: 1} }); // 渲染進(jìn)程內(nèi)部 const webview = document.querySelector("webview") webview.send("event-from-renderer", {a: 1})總結(jié)
這三種通信方式是最基礎(chǔ)的,在此之上進(jìn)行排列組合也是很常見的,這個(gè)由開發(fā)者自行拓展即可。
舉一個(gè)小例子:webview內(nèi)部觸發(fā)更換皮膚功能 -> 通知渲染進(jìn)程同步更新皮膚 -> 渲染進(jìn)程收到消息,向其他渲染進(jìn)程通信 -> 同步更新皮膚完成。
最后歡迎大家在評(píng)論區(qū)討論,技術(shù)交流 & 內(nèi)推 -> zhongli@qunhemail.com
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/114820.html
摘要:為了能使不同的進(jìn)程互相訪問資源并進(jìn)行協(xié)調(diào)工作,才有了進(jìn)程間通信。此時(shí),就需要與渲染進(jìn)程通信了。發(fā)消息,渲染進(jìn)程收消息內(nèi)部使用來發(fā)消息。 作者:鐘離,酷家樂PC客戶端負(fù)責(zé)人原文地址:https://webfe.kujiale.com/electron-ku-jia-le-ke-hu-duan-kai-fa-shi-jian-fen-xiang-jin-cheng-tong-xin/酷家...
摘要:為了能使不同的進(jìn)程互相訪問資源并進(jìn)行協(xié)調(diào)工作,才有了進(jìn)程間通信。此時(shí),就需要與渲染進(jìn)程通信了。發(fā)消息,渲染進(jìn)程收消息內(nèi)部使用來發(fā)消息。 作者:鐘離,酷家樂PC客戶端負(fù)責(zé)人原文地址:https://webfe.kujiale.com/electron-ku-jia-le-ke-hu-duan-kai-fa-shi-jian-fen-xiang-jin-cheng-tong-xin/酷家...
摘要:系列文章酷家樂客戶端開發(fā)實(shí)踐分享入坑篇酷家樂客戶端開發(fā)實(shí)踐分享軟件自動(dòng)更新酷家樂客戶端開發(fā)實(shí)踐分享瀏覽器啟動(dòng)客戶端酷家樂客戶端開發(fā)實(shí)踐分享進(jìn)程通信酷家樂客戶端開發(fā)實(shí)踐分享下載管理器不定期更新本文的初衷所使用的技術(shù)棧和前端工程師完美契合。 作者:鐘離,酷家樂PC客戶端負(fù)責(zé)人原文地址:https://webfe.kujiale.com/electron-ku-jia-le-ke-hu-d...
摘要:系列文章酷家樂客戶端開發(fā)實(shí)踐分享入坑篇酷家樂客戶端開發(fā)實(shí)踐分享軟件自動(dòng)更新酷家樂客戶端開發(fā)實(shí)踐分享瀏覽器啟動(dòng)客戶端酷家樂客戶端開發(fā)實(shí)踐分享進(jìn)程通信酷家樂客戶端開發(fā)實(shí)踐分享下載管理器不定期更新本文的初衷所使用的技術(shù)棧和前端工程師完美契合。 作者:鐘離,酷家樂PC客戶端負(fù)責(zé)人原文地址:https://webfe.kujiale.com/electron-ku-jia-le-ke-hu-d...
摘要:作者鐘離,酷家樂客戶端負(fù)責(zé)人原文地址酷家樂客戶端下載地址文章背景在酷家樂客戶端在改版成功后,我們積累了許多的寶貴的經(jīng)驗(yàn)和最佳實(shí)踐。用戶在電腦上安裝客戶端,實(shí)際上會(huì)將客戶端代碼文件持久儲(chǔ)存到本機(jī)。通常我們會(huì)在軟件啟動(dòng)時(shí)檢查更新。 作者:鐘離,酷家樂PC客戶端負(fù)責(zé)人原文地址:https://webfe.kujiale.com/electron-autoupdate/酷家樂客戶端:下載地址...
閱讀 3924·2021-10-12 10:12
閱讀 2886·2021-09-10 11:18
閱讀 3672·2019-08-30 15:54
閱讀 2808·2019-08-30 15:53
閱讀 638·2019-08-30 13:54
閱讀 965·2019-08-30 13:21
閱讀 2259·2019-08-30 12:57
閱讀 1687·2019-08-30 11:10