当前位置: 首页 > news >正文

Electron+React 搭建桌面应用

创建应用程序

创建 Electron 应用

使用 Webpack 创建新的 Electron 应用程序:

npm init electron-app@latest my-new-app -- --template=webpack

启动应用

npm start

设置 Webpack 配置

添加依赖包,确保可以正确使用 JSX 和其他 React 功能:

npm install --save-dev @babel/core @babel/preset-react babel-loader

修改配置文件:

// webpack.rules.js
module.exports = [// ... existing loader config ...{test: /\.jsx?$/,use: {loader: 'babel-loader',options: {exclude: /node_modules/,presets: ['@babel/preset-react']}}}// ... existing loader config ...
];

集成前端 React

添加 React 依赖

将基本的 React 包添加到 dependencies:

npm install --save react react-dom

集成 React 代码

现在可以开始在 Electron 中编写和使用 React 组件了。在 src/app.jsx 中编写 React 代码:

import * as React from 'react';
import { createRoot } from 'react-dom/client';const root = createRoot(document.body);
root.render(<h2>Hello from React!</h2>);

添加渲染进程

将 React 代码添加到渲染进程 src/renderer.js 中:

import './index.css';
import './app.jsx';
console.log('👋 This message is being logged by "renderer.js", included via webpack');

启动应用

npm start

主进程和渲染进程通信

在 Electron 中,渲染进程和主进程之间的通信需要通过预加载脚本 preload.js 来进行,preload.js 的作用就是作为渲染进程和主进程之间通信的桥梁。

渲染进程 -> 主进程

当用户在界面上点击最小化或者最大化,或者更改某些全局设置(如语言偏好、主题等)时,这些更改通常由渲染进程触发,但实际执行由主进程负责。在这种情况下,渲染进程调用主进程的方法以应用这些更改,但不需要等待主进程的回包,因为用户界面的响应可以立即更新,而不必等待设置保存的确认。

预加载脚本

在预加载脚本 preload.js 中定义双方通信方法,使用 ipcRenderer.send 将信息发往主进程:

// See the Electron documentation for details on how to use preload scripts:
// https://www.electronjs.org/docs/latest/tutorial/process-model#preload-scriptsconst {contextBridge, ipcRenderer} = require('electron');contextBridge.exposeInMainWorld('my_app_name', {// 最小化minimize: () => {ipcRenderer.send('minimize')},// 最大化maximize: () => {ipcRenderer.send('maximize')}
})

渲染进程

在渲染进程中,使用 window.app_name.func_name 调用预加载脚本里的方法:

import * as React from 'react';
import { createRoot } from 'react-dom/client';const root = createRoot(document.body);
root.render(<div><button onClick={() => {window.my_app_name.minimize()}}>最小化</button><button onClick={() => {window.my_app_name.maximize()}}>最大化</button>
</div>);

主进程

在主进程中,使用 ipc.Main.on 监听事件,并执行具体操作:

const {app, BrowserWindow, ipcMain} = require('electron');
const path = require('node:path');let mainWindow;const createWindow = () => {// 创建浏览器窗口。mainWindow = new BrowserWindow({width: 800,height: 600,webPreferences: {preload: MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY, // 预加载脚本,用于在主进程和渲染进程之间安全地共享数据},});// 加载应用的index.html。mainWindow.loadURL(MAIN_WINDOW_WEBPACK_ENTRY);// 打开开发者工具。mainWindow.webContents.openDevTools();
};// .....其他代码.....// 监听来自渲染进程的'minimize'消息,最小化主窗口。
ipcMain.on('minimize', event => {mainWindow.minimize();
})// 监听来自渲染进程的'maximize'消息,最大化主窗口。
ipcMain.on('maximize', event => {mainWindow.maximize();
})

渲染进程 <-> 主进程

在 Electron 中,用户可能需要打开、保存或者删除文件。当用户点击一个按钮或者菜单项来执行这些操作时,渲染进程会向主进程发送一个消息,请求执行相应的操作。主进程接到消息后,调用系统API来完成文件操作,并将操作结果发送回渲染进程,渲染进程根据主进程的响应更新界面状态等。

预加载脚本

在预加载脚本 preload.js 中定义双方通信方法,使用 ipcRenderer.invoke 将信息发往主进程,并将结果返回到渲染进程:

// See the Electron documentation for details on how to use preload scripts:
// https://www.electronjs.org/docs/latest/tutorial/process-model#preload-scriptsconst {contextBridge, ipcRenderer} = require('electron');contextBridge.exposeInMainWorld('my_app_name', {// 选择文件chooseFile: async () => {const path = await ipcRenderer.invoke('choose-file');return path;},
})

渲染进程

在渲染进程中,使用 window.app_name.func_name 调用预加载脚本里的方法:

import * as React from 'react';
import {createRoot} from 'react-dom/client';const root = createRoot(document.body);
root.render(<div><button onClick={() => {window.my_app_name.chooseFile().then(result => {console.log(result['filePaths'][0])alert(result['filePaths'][0])})}}>选择文件</button>
</div>);

主进程

在主进程中,使用 ipc.handle 监听事件,执行操作并将结果返回给预加载脚本:

const {app, BrowserWindow, ipcMain, dialog} = require('electron');
const path = require('node:path');let mainWindow;const createWindow = () => {// 创建浏览器窗口。mainWindow = new BrowserWindow({width: 800,height: 600,webPreferences: {preload: MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY, // 预加载脚本,用于在主进程和渲染进程之间安全地共享数据},});// 加载应用的index.html。mainWindow.loadURL(MAIN_WINDOW_WEBPACK_ENTRY);// 打开开发者工具。mainWindow.webContents.openDevTools();
};// .....其他代码.....// 监听来自渲染进程的'choose-file'消息,选择文件,并将结果返回给预加载脚本。
ipcMain.handle('choose-file', async (event, data) => {const result = await dialog.showOpenDialog(BrowserWindow.getFocusedWindow(), {properties: ['openFile']});return result
});

主进程 -> 渲染进程

Electron 应用启动时,有时候需要由主进程从本地存储或者服务器来加载应用的配置信息(窗口大小、位置、主题设置等)。主进程加载完设置后,通过单向通信将配置信息发送给渲染进程。渲染进程接收到配置信息后,根据这些信息调整界面布局或者样式。通常用于初始化或者更新应用的界面设置。

主进程

在主进程中,使用 mainWindow.webContents.send 将消息发送给预加载脚本:

const {app, BrowserWindow, ipcMain, dialog} = require('electron');
const path = require('node:path');let mainWindow;const createWindow = () => {// 创建浏览器窗口。mainWindow = new BrowserWindow({width: 800,height: 600,webPreferences: {preload: MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY, // 预加载脚本,用于在主进程和渲染进程之间安全地共享数据},});// 加载应用的index.html。mainWindow.loadURL(MAIN_WINDOW_WEBPACK_ENTRY);// 打开开发者工具。mainWindow.webContents.openDevTools();// 设置十秒钟后发送消息到渲染进程setTimeout(() => {mainWindow.webContents.send('message-from-main', 'Hello from main process!');}, 3000); // 10000 毫秒等于 10 秒
};// .....其他代码.....

预加载脚本

在预加载脚本 preload.js 中使用 ipcRenderer.on 监听消息,然后通过回调函数将消息传递给渲染进程:

// See the Electron documentation for details on how to use preload scripts:
// https://www.electronjs.org/docs/latest/tutorial/process-model#preload-scriptsconst {contextBridge, ipcRenderer} = require('electron');contextBridge.exposeInMainWorld('my_app_name', {msgFromMain: (callback) => ipcRenderer.on('message-from-main', (event, message) => {callback(message);})
})

渲染进程

在渲染进程中,使用 useEffect 来监听消息并作出相应处理:

import React, { useEffect, useState } from 'react';const App = () => {const [messageFromMain, setMessageFromMain] = useState('');useEffect(() => {// 调用预加载脚本中暴露的 msgFromMain 方法window.my_app_name.msgFromMain((message) => {setMessageFromMain(message);});// 清理函数(可选),如果需要的话可以在这里注销监听器return () => {// 如果有必要的话,可以在这里注销监听器,但在这个例子中我们不需要,因为ipcRenderer.on会自动管理监听器的生命周期};}, []); // 确保这个 effect 只运行一次return (<div>{/* 显示从主进程接收到的消息 */}<p>{messageFromMain}</p></div>);
};export default App;

【1】React | Electron Forge

相关文章:

Electron+React 搭建桌面应用

创建应用程序 创建 Electron 应用 使用 Webpack 创建新的 Electron 应用程序&#xff1a; npm init electron-applatest my-new-app -- --templatewebpack 启动应用 npm start 设置 Webpack 配置 添加依赖包&#xff0c;确保可以正确使用 JSX 和其他 React 功能&#xff…...

基于Android的记单词App系统的设计与实现

博主介绍&#xff1a;✌IT徐师兄、7年大厂程序员经历。全网粉丝15W、csdn博客专家、掘金/华为云//InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;&#x1f3…...

ELK 企业级日志分析系统 简单介绍

目录 一 ELK 简介 1&#xff0c; elk 是什么 2&#xff0c;elk 架构图 3&#xff0c;elk 日志处理步骤 二 Elasticsearch 简介 1&#xff0c; Elasticsearch 是什么 2&#xff0c; Elasticsearch 的核心概念 3&#xff0c; Elasticsearch 的原理 三 Logstas…...

GET与POST:详述HTTP两大请求方法的语义、数据处理机制、安全特性与适用场景

GET和POST方法在HTTP请求中具有明确的角色分工和特性差异。GET适用于读取操作和不敏感数据的传递&#xff0c;强调可缓存性和安全性&#xff0c;而POST适用于写入操作和敏感数据的提交&#xff0c;提供了更大的数据承载能力和更强的隐私保护。本文详细介绍了GET与POST请求方法的…...

Unity Pro 2019 for Mac:专业级游戏引擎,助力创意无限延伸!

Unity Pro 2019是一款功能强大的游戏开发引擎&#xff0c;其特点主要体现在以下几个方面&#xff1a; 强大的渲染技术&#xff1a;Unity Pro 2019采用了新的渲染技术&#xff0c;包括脚本化渲染流水线&#xff0c;能够轻松自定义渲染管线&#xff0c;通过C#代码和材料材质&…...

C++设计模式:单例模式(十)

1、单例设计模式 单例设计模式&#xff0c;使用的频率比较高&#xff0c;整个项目中某个特殊的类对象只能创建一个 并且该类只对外暴露一个public方法用来获得这个对象。 单例设计模式又分懒汉式和饿汉式&#xff0c;同时对于懒汉式在多线程并发的情况下存在线程安全问题 饿汉…...

openssl3.2 - exp - zlib

文章目录 openssl3.2 - exp - zlib概述笔记命令行实现程序实现备注 - 压缩时无法base64压缩时无法带口令压缩实现 - 对buffer进行压缩和解压缩测试效果工程实现main.cppCOsslZlibBuffer.hCOsslZlibBuffer.cpp总结END openssl3.2 - exp - zlib 概述 客户端和服务端进行数据交换…...

【故事】无人机学习之旅

今天是清明假期最后一天&#xff0c;晚上在看无人机的东西&#xff0c;翻到了欣飞鸽的知乎主页&#xff0c;读了他的一些文章。虽不曾相识&#xff0c;但感觉我们有很多相似的经历&#xff0c;也想记录一下自己的无人机学习之旅。 青铜&#xff1a;从使用开源飞控开始 我在大…...

torch.mean()的使用方法

对一个三维数组的每一维度进行操作 1&#xff0c;dim0 a torch.Tensor([0, 1, 2, 3, 4, 5,6,7]).view(2, 2, 2) print(a) mean torch.mean(a, 0) print(mean, mean.shape) 输出结果&#xff1a; tensor([[[0., 1.], [2., 3.]], [[4., 5.], [6., 7.]]]) tensor([[2., …...

windows安装Redis,Mongo,ES并快速基本掌握开发流程

前言 这里只是一些安装后的基础操作&#xff0c;后期会学习更加深入的操作 基础操作 前言RedisRedis启动idea集成Redisjedis技术 Mongodbwindows版Mongodb的安装idea整合Mongodb ES(Elasticsearch)ESwindows下载ES文档操作idea整合ES低级别ES整合高级别ES整合 Redis Redis是…...

ruoyi-nbcio-plus基于vue3的flowable的自定义业务提交申请组件的升级修改

更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码&#xff1a; https://gitee.com/nbacheng/ruoyi-nbcio 演示地址&#xff1a;RuoYi-Nbcio后台管理系统 http://122.227.135.243:9666/ 更多nbcio-boot功能请看演示系统 gitee源代码地址 后端代码&#xff1a…...

掌握网络抓取技术:利用RobotRules库的Perl下载器一览小红书的世界

引言 在信息时代的浪潮下&#xff0c;人们对于获取和分析海量网络数据的需求与日俱增。网络抓取技术作为满足这一需求的关键工具&#xff0c;正在成为越来越多开发者的首选。而Perl语言&#xff0c;以其卓越的文本处理能力和灵活的特性&#xff0c;脱颖而出&#xff0c;成为了…...

典型新能源汽车热管理系统方案分析

目前行业具有代表性的热管理系统有PTC电加热方案、热泵方案&#xff08;特斯拉八通阀热泵、吉利直接式热泵&#xff09;、威马的柴油加热方案以及以理想为代表的插电式混动车方案。 小鹏P7整车热管理方案分析&#xff08;PTC电加热方案&#xff09; 小鹏P7作为小鹏汽车的第2款…...

使用Docker部署开源项目FreeGPT35来免费调用ChatGPT3.5 API

Vercel部署FreeGPT35有严重限制&#xff0c;玩玩就好&#xff0c;真用还是得docker。 限制原因: Vercel的流式响应并不是一开始写流&#xff0c;客户端就能立刻收到响应流&#xff0c;而是先写到一个缓冲区&#xff0c;当流关闭才一股脑的流式响应回来(不是实时流) 因此导致: …...

《Linux运维实战:Kylin V10操作系统开启安装软件保留缓存设置》

总结&#xff1a;整理不易&#xff0c;如果对你有帮助&#xff0c;可否点赞关注一下&#xff1f; 更多详细内容请参考&#xff1a;Linux运维实战总结 一、操作步骤 1、改系统/etc/yum.conf配置文件&#xff0c;开启安装软件保留缓存设置 [rootecs-90c2-0003 ~]# vim /etc/yum.…...

视频生成技术:从GAN到Latte

GANs Diffusion Model...

机器学习中的激活函数

激活函数存在的意义&#xff1a; 激活函数决定了某个神经元是否被激活&#xff0c;当这个神经元接收到的信息是有用或无用的时候&#xff0c;激活函数决定了对这个神经元接收到的信息是留下还是抛弃。如果不加激活函数&#xff0c;神经元仅仅做线性变换&#xff0c;那么该神经网…...

LinuxAndroid: 旋转编码器input输入事件适配(旋转输入)

rk3588s: 旋转编码器input输入事件适配 基于Android 12 kernel-5.10版本 参考文档&#xff1a; https://blog.csdn.net/szembed/article/details/131551950 Linux 输入设备调试详解&#xff08;零基础开发&#xff09;Rotary_Encoder旋转编码器驱动 通用GPIO为例 挂载input输…...

机器学习和深度学习-- 李宏毅(笔记与个人理解)Day10

Day 10 Genaral GUidance training Loss 不够的case Loss on Testing data over fitting 为什么over fitting 留到下下周哦~~ 期待 solve CNN卷积神经网络 Bias-Conplexiy Trade off cross Validation how to split? N-fold Cross Validation mismatch 这节课总体听下来比较…...

perl 交叉编译

前言 Perl是一种高级、通用、解释型、动态的编程语言。Perl设计的初衷是为了更好地处理文本处理任务&#xff0c;但随着时间的发展&#xff0c;现在它已经变成了一种强大的一般目的编程语言。Perl支持面向过程和面向对象的编程风格。 Perl的特点&#xff1a; 强大的字符串处…...

R语言AI模型部署方案:精准离线运行详解

R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...

将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?

Otsu 是一种自动阈值化方法&#xff0c;用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理&#xff0c;能够自动确定一个阈值&#xff0c;将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...

页面渲染流程与性能优化

页面渲染流程与性能优化详解&#xff08;完整版&#xff09; 一、现代浏览器渲染流程&#xff08;详细说明&#xff09; 1. 构建DOM树 浏览器接收到HTML文档后&#xff0c;会逐步解析并构建DOM&#xff08;Document Object Model&#xff09;树。具体过程如下&#xff1a; (…...

Rust 异步编程

Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...

RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程

本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型应用开发学习视频及资料&#xff0c;尽在聚客AI学院。 本文全面剖析RNN核心原理&#xff0c;深入讲解梯度消失/爆炸问题&#xff0c;并通过LSTM/GRU结构实现解决方案&#xff0c;提供时间序列预测和文本生成…...

【C++进阶篇】智能指针

C内存管理终极指南&#xff1a;智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...

基于Springboot+Vue的办公管理系统

角色&#xff1a; 管理员、员工 技术&#xff1a; 后端: SpringBoot, Vue2, MySQL, Mybatis-Plus 前端: Vue2, Element-UI, Axios, Echarts, Vue-Router 核心功能&#xff1a; 该办公管理系统是一个综合性的企业内部管理平台&#xff0c;旨在提升企业运营效率和员工管理水…...

jmeter聚合报告中参数详解

sample、average、min、max、90%line、95%line,99%line、Error错误率、吞吐量Thoughput、KB/sec每秒传输的数据量 sample&#xff08;样本数&#xff09; 表示测试中发送的请求数量&#xff0c;即测试执行了多少次请求。 单位&#xff0c;以个或者次数表示。 示例&#xff1a;…...

WebRTC从入门到实践 - 零基础教程

WebRTC从入门到实践 - 零基础教程 目录 WebRTC简介 基础概念 工作原理 开发环境搭建 基础实践 三个实战案例 常见问题解答 1. WebRTC简介 1.1 什么是WebRTC&#xff1f; WebRTC&#xff08;Web Real-Time Communication&#xff09;是一个支持网页浏览器进行实时语音…...

OD 算法题 B卷【正整数到Excel编号之间的转换】

文章目录 正整数到Excel编号之间的转换 正整数到Excel编号之间的转换 excel的列编号是这样的&#xff1a;a b c … z aa ab ac… az ba bb bc…yz za zb zc …zz aaa aab aac…; 分别代表以下的编号1 2 3 … 26 27 28 29… 52 53 54 55… 676 677 678 679 … 702 703 704 705;…...