当前位置: 首页 > 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; 强大的字符串处…...

基于大模型的 UI 自动化系统

基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...

深入剖析AI大模型:大模型时代的 Prompt 工程全解析

今天聊的内容&#xff0c;我认为是AI开发里面非常重要的内容。它在AI开发里无处不在&#xff0c;当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗"&#xff0c;或者让翻译模型 "将这段合同翻译成商务日语" 时&#xff0c;输入的这句话就是 Prompt。…...

Day131 | 灵神 | 回溯算法 | 子集型 子集

Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 笔者写过很多次这道题了&#xff0c;不想写题解了&#xff0c;大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...

CentOS下的分布式内存计算Spark环境部署

一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架&#xff0c;相比 MapReduce 具有以下核心优势&#xff1a; 内存计算&#xff1a;数据可常驻内存&#xff0c;迭代计算性能提升 10-100 倍&#xff08;文档段落&#xff1a;3-79…...

微信小程序云开发平台MySQL的连接方式

注&#xff1a;微信小程序云开发平台指的是腾讯云开发 先给结论&#xff1a;微信小程序云开发平台的MySQL&#xff0c;无法通过获取数据库连接信息的方式进行连接&#xff0c;连接只能通过云开发的SDK连接&#xff0c;具体要参考官方文档&#xff1a; 为什么&#xff1f; 因为…...

第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词

Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵&#xff0c;其中每行&#xff0c;每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid&#xff0c;其中有多少个 3 3 的 “幻方” 子矩阵&am…...

sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!

简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求&#xff0c;并检查收到的响应。它以以下模式之一…...

沙箱虚拟化技术虚拟机容器之间的关系详解

问题 沙箱、虚拟化、容器三者分开一一介绍的话我知道他们各自都是什么东西&#xff0c;但是如果把三者放在一起&#xff0c;它们之间到底什么关系&#xff1f;又有什么联系呢&#xff1f;我不是很明白&#xff01;&#xff01;&#xff01; 就比如说&#xff1a; 沙箱&#…...

鸿蒙(HarmonyOS5)实现跳一跳小游戏

下面我将介绍如何使用鸿蒙的ArkUI框架&#xff0c;实现一个简单的跳一跳小游戏。 1. 项目结构 src/main/ets/ ├── MainAbility │ ├── pages │ │ ├── Index.ets // 主页面 │ │ └── GamePage.ets // 游戏页面 │ └── model │ …...

leetcode73-矩阵置零

leetcode 73 思路 记录 0 元素的位置&#xff1a;遍历整个矩阵&#xff0c;找出所有值为 0 的元素&#xff0c;并将它们的坐标记录在数组zeroPosition中置零操作&#xff1a;遍历记录的所有 0 元素位置&#xff0c;将每个位置对应的行和列的所有元素置为 0 具体步骤 初始化…...