Electron 项目实战 01:主进程与渲染进程通信

项目搭建

  1. 创建命令

    bash 复制代码
    mkdir electron_app
    cd electron_app
    npm init -y
    yarn add electron -D
  2. 必要的配置

    • package.json

      bash 复制代码
      {
        "name": "my-electron-app",
        "version": "1.0.0",
        "main": "main.js",
        "license": "MIT",
        "scripts": {
          "dev": "electron ."
        },
        "devDependencies": {
          "electron": "^28.0.0"
        }
      }
      • main:设置入口文件
      • scripts: 添加开发命令
    • main.js

      jsx 复制代码
      const { app, BrowserWindow } = require("electron");
      
      const createWindow = () => {
      	const win = new BrowserWindow({
      		width: 800,
      		height: 600,
      	});
      	
      	// 添加首页面
      	win.loadFile("index.html");
      };
      
      //! 1. app已准备就绪
      app.whenReady().then(() => {
      	//2. 创建一个win窗口
      	createWindow();
      	console.log(process.platform);
      	
        //3. 添加预防处理,如果app已处于active状态还没window自动创建一个
      	app.on("activate", () => {
      		if (BrowserWindow.getAllWindows().length === 0) {
      			createWindow();
      		}
      	});
      });
      
      app.on("window-all-closed", () => {
      	// 说明:不为mac os 平台,添加此退出命令
      	if (process.platform !== "darwin") {
      		console.log("quit");
      		app.quit();
      	}
      });
  • index.html

    jsx 复制代码
    <!DOCTYPE html>
    <html>
    
    <head>
    	<meta charset="UTF-8" />
    	<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
    	<meta http-equiv="Content-Security-Policy"
    				content="default-src 'self'; script-src 'self'" />
    	<meta http-equiv="X-Content-Security-Policy"
    				content="default-src 'self'; script-src 'self'" />
    	<title>Hello from Electron renderer!</title>
    </head>
    
    <body>
    	<h1>Hello from Electron renderer!</h1>
    	<p>👋</p>
    </body>
    
    </html>
  • yarn dev 看下效果

说明最简单的项目已搭建好,我们来看下Render process 与 Main process 是如何通讯的

主进程与渲染进程通讯

  • 为了让代码更加清晰,我们将渲染进程的代码写到renderer.js中
  • 由于Electron是一个Node环境,可以完全的访问系统,为了安全我们添加一个preload 脚本来建立一个桥,让渲染进程与主进程进行通信
  • 利用Electron包中的ipcMain 和 ipcRenderer 进行通信

具体代码:

  • main.js

    jsx 复制代码
    const { app, BrowserWindow, ipcMain } = require("electron");
    const path = require("node:path");
    
    const createWindow = () => {
    	const win = new BrowserWindow({
    		width: 800,
    		height: 600,
    		webPreferences: {
    			//! 3.注意这里添加了预加载preload.js
    			preload: path.join(__dirname, "preload.js"),
    		},
    	});
    
    	win.loadFile("index.html");
    };
    
    app.whenReady().then(() => {
    	//! 主进程,处理渲染进程的消息
    	ipcMain.handle("ping", () => {
    		return `I'm ipcMain`;
    	});
    
    	// ! 1.主进程监听来自渲染进程的消息
    	ipcMain.on("message-from-renderer", (event, arg) => {
    		console.log("Renderer Process Message:", arg);
    
    		//! 2.发送回复消息到渲染进程
    		event.sender.send("message-from-main", "Hello from main process!");
    	});
    
    	createWindow();
    	console.log(process.platform);
    	app.on("activate", () => {
    		if (BrowserWindow.getAllWindows().length === 0) {
    			createWindow();
    		}
    	});
    });
    
    app.on("window-all-closed", () => {
    	if (process.platform !== "darwin") {
    		console.log("quit");
    		app.quit();
    	}
    });
  • preload.js

    jsx 复制代码
    const { contextBridge, ipcRenderer } = require("electron");
    
    contextBridge.exposeInMainWorld("versions", {
    	node: () => process.versions.node,
    	chrome: () => process.versions.chrome,
    	electron: () => process.versions.electron,
    	//! 给桥上线添加对应方法
    	ping: (name) => ipcRenderer.invoke("ping", name),
    });
    
    //! 1.添加渲染进程与主进程的桥梁接口
    contextBridge.exposeInMainWorld("electronAPI", {
    	sendMessageToMain: (message) => {
    		ipcRenderer.send("message-from-renderer", message);
    	},
    	receiveMessageFromMain: (callback) => {
    		ipcRenderer.on("message-from-main", (event, message) => {
    			callback(message);
    		});
    	},
    });
  • renderer.js

    jsx 复制代码
    const information = document.getElementById("info");
    information.innerText = `This app is using Chrome (v${versions.chrome()}), Node.js (v${versions.node()}), and Electron (v${versions.electron()})`;
    
    const func = async () => {
    	//! 渲染进程, 调用主进程方法
    	const response = await window.versions.ping();
    	console.log("渲染进程接收主进程的消息:", response); // prints out 'pong'
    };
    
    func();
    
    //! 1.渲染进程往主进程发送消息
    window.electronAPI.sendMessageToMain("Hello from the renderer process!");
    //! 2.渲染进程接收到主进程的消息
    window.electronAPI.receiveMessageFromMain((message) => {
    	console.log(`Received message from main process: ${message}`);
    });

yarn dev 看下效果

  • 主进程收到渲染进程消息(注意:主进程接收到的消息打印在终端控制台)
  • 渲染进程收到主进程消息

说明:可能你不知道打开Electron App的日志控制台,看下图:

总结

  • 整体来说参看官方文档和网上的文章就可以轻松实现

参考文献

更多

家人们,我最近花了2个多月开源了一个文章发布助手artipub,可以帮你一键将markdown发布至多平台(发布和更新),方便大家更好的传播知识和分享你的经验。

目前已支持平台:个人博客、Medium、Dev.to(未来会支持更多平台)

官网地址:https://artipub.github.io/artipub/

仓库地址:https://github.com/artipub/artipub

目前库已可以正常使用,欢迎大家体验、如果你有任何问题和建议都可以提Issue给我反馈。

如果你感兴趣,特别欢迎你的加入,让我们一起完善好这个工具。

帮忙点个star⭐,让更多人知道这个工具,感谢大家🙏

相关推荐
编程猪猪侠3 分钟前
Tailwind CSS 自定义工具类与主题配置指南
前端·css
qhd吴飞7 分钟前
mybatis 差异更新法
java·前端·mybatis
YGY Webgis糕手之路29 分钟前
OpenLayers 快速入门(九)Extent 介绍
前端·经验分享·笔记·vue·web
患得患失94931 分钟前
【前端】【vueDevTools】使用 vueDevTools 插件并修改默认打开编辑器
前端·编辑器
ReturnTrue86832 分钟前
Vue路由状态持久化方案,优雅实现记住表单历史搜索记录!
前端·vue.js
UncleKyrie38 分钟前
一个浏览器插件帮你查看Figma设计稿代码图片和转码
前端
遂心_40 分钟前
深入解析前后端分离中的 /api 设计:从路由到代理的完整指南
前端·javascript·api
你听得到111 小时前
Flutter - 手搓一个日历组件,集成单日选择、日期范围选择、国际化、农历和节气显示
前端·flutter·架构
风清云淡_A1 小时前
【REACT18.x】CRA+TS+ANTD5.X封装自定义的hooks复用业务功能
前端·react.js
@大迁世界1 小时前
第7章 React性能优化核心
前端·javascript·react.js·性能优化·前端框架