禹神electron学习~

embedded/2024/10/20 15:09:15/

最近时间比较富裕  咱们浅浅来学习electron 

视频在这禹神:一小时快速上手Electron,前端Electron开发教程_哔哩哔哩_bilibili

 先看下流程模型

 先决条件

 首先第一步 查看你的node和npm版本 

创建你的应用

 创建一个文件夹  我创建的名称为my-electron-app

搭建项目脚手架

然后打开vscode

javascript">npm init

交互式 init 命令将提示你在配置中设置一些字段。出于本教程的目的,需要遵循一些规则:

  • entry point 应该是 main.js

  • author(名字创建者) 和 description(描述) 可以是任何值,但对于 应用打包 是必需的。

你的 package.json 文件应如下所示:

javascript">{"name": "my-electron-app","version": "1.0.0","description": "Hello World!","main": "index.js","scripts": {"test": "echo \"Error: no test specified\" && exit 1"},"author": "zhou","license": "ISC"
}

 划重点!!!!必填必填!!!打包要用到!!

然后,将 electron 包安装到应用的 devDependencies 中。 

javascript">npm install --save-dev electron

 最后,你希望能够执行 Electron。在 package.json 配置的 scripts 字段中,添加 start 命令,如下所示:

javascript">{"scripts": {"start": "electron ."}
}

此 start 命令将允许你在开发模式下打开应用。

javascript">npm start

 注意:该脚本告诉 Electron 在项目的根文件夹上运行。在此阶段,你的应用将立即抛出错误,告诉你它找不到要运行的应用。如下:

运行主进程 

 

这是什么意思呢就是main是一个主入口  而现在没有这个主入口  它找不到   所以就报错了  那怎么解决这个问题呢  也很好解决  加上就是了吗(package.json里边别忘记修改哦)

 创建网页

在项目的根文件夹中创建pages文件夹在下边创建 index.html和index.css 文件:

javascript"><!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><!-- https://web.nodejs.cn/en-US/docs/Web/HTTP/CSP --><meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'"><title>Hello World!</title><link rel="stylesheet" href="./index.css">
</head><body><h1>欢迎学习Electron开发!!!</h1>
</body></html>

 在浏览器窗口中打开网页

现在你已经有了一个网页,将其加载到应用窗口中。为此,你需要两个 Electron 模块:

  • app 模块,控制应用的事件生命周期。

  • BrowserWindow 模块,用于创建和管理应用窗口。

由于主进程运行 Node.js,因此你可以将它们作为 CommonJS 模块导入到 main.js 文件的顶部:

 

javascript">const { app, BrowserWindow } = require('electron')

然后,添加一个 createWindow() 函数,将 index.html 加载到新的 BrowserWindow 实例中。

javascript">const createWindow = () => {const win = new BrowserWindow({width: 800,height: 600,});win.loadFile("./pages/index.html");
};

接下来,调用此 createWindow() 函数来打开窗口。

在 Electron 中,浏览器窗口只能在 app 模块的 ready 事件被触发后创建。你可以使用 app.whenReady() API 等待此事件。在 whenReady() 解决其 Promise 后调用 createWindow()。或者是app.on("ready")来  此处我喜欢用后者  因为他俩是一样的  用哪个无所谓哈

javascript">const { app, BrowserWindow } = require("electron");
const createWindow = () => {const win = new BrowserWindow({width: 800,height: 600,});win.loadFile("./pages/index.html");
};
// app.whenReady().then(() => {
//   createWindow();// });
app.on("ready", () => {createWindow();
});

 然后运行一下npm start

一个桌面应用就出现了

  管理窗口的生命周期

尽管你现在可以打开浏览器窗口,但你将需要一些额外的样板代码,以使其感觉对每个平台更加原生。应用窗口在每个操作系统上的行为都不同,Electron 让开发者有责任在他们的应用中实现这些约定。

一般来说,你可以使用 process 全局的 platform 属性来运行专门针对某些操作系统的代码。

所有窗口关闭后退出应用(Windows 和 Linux)

在 Windows 和 Linux 上,退出所有窗口通常会完全退出应用。

要实现此目的,请监听 app 模块的 'window-all-closed' 事件,如果用户不在 macOS (darwin) 上,则调用 app.quit()。

javascript">app.on('window-all-closed', () => {if (process.platform !== 'darwin') app.quit()
})
如果没有打开窗口,则打开一个窗口 (macOS)

Linux 和 Windows 应用在没有打开任何窗口时退出,而 macOS 应用通常即使没有打开任何窗口也会继续运行,并且在没有可用窗口时激活应用应该打开一个新窗口。

要实现此功能,请监听 app 模块的 activate 事件,如果没有打开浏览器窗口,则调用现有的 createWindow() 方法。

由于无法在 ready 事件之前创建窗口,因此你应该仅在应用初始化后监听 activate 事件。通过从现有 whenReady() 回调中附加事件监听器来执行此操作。

javascript">app.on("ready", () => {createWindow();app.on("activate", () => {if (BrowserWindow.getAllWindows().length === 0) createWindow();});
});

如果你不想要上边那些个小标题  就加个属性 autoHideMenuBar:true

效果是这样的

 

看好进程  有主进程和渲染进程  我们还没看见渲染进程  不怕 我们在pages里写一个render.js,那怎么引入js呢  就很简单呀在html直接引入就好了

render.js与index。html的交互

javascript">const btn1 = document.getElementById("btn1");
btn1.onclick = () => {alert("你点我了");
};

  点击效果图如下

 

 那他俩是隔离开的  怎么通信呢

就比如我想要alert弹窗的时候我想要拿到node的版本怎么拿呢

在主进程我是可以拿到的

但是渲染进程就不行 控制器怎么调出来的ctrl+shift+i

为啥会报错 因为render.js是渲染环境  他没法拿到node的process方法 那怎么办

使用预加载脚本从渲染器访问 Node.js

现在,最后要做的是将 Electron 的版本号及其依赖打印到你的网页上。

在主进程中通过 Node 的全局 process 对象访问此信息很简单。但是,你不能只从主进程编辑 DOM,因为它无法访问渲染器的 document 上下文。他们处于完全不同的进程!

这时将预加载脚本附加到渲染器就派上用场了。预加载脚本在加载渲染器进程之前运行,并且可以访问渲染器全局变量(例如 window 和 document)和 Node.js 环境。

需要个预加载脚本通信  在根目录下新建个preload.js文件

使preload能进行打印 main.js需要加上这段代码

javascript">    webPreferences: {preload: path.resolve(__dirname, "./preload.js"),},

然后npm start运行下

就能看到是preload先执行 然后执行的render

那我现在想要在渲染进程里边打印process 我就得通过perload(它虽然是运行在渲染进程的,但是它可以使用部分node语法 就比如process)尝试下

打印出来了   

那么 预加载文件如何把process传给渲染进程render.js呢

需要个属性

javascript">const { contextBridge } = require("electron");contextBridge.exposeInMainWorld("abc", {xyz: 100,});

先看这是没有写

// contextBridge.exposeInMainWorld("abc", {

//   xyz: 100,

// });

注释掉了  所以不执行  我们在控制台打印window  可见里边没有这个属性 

那我把注释打开看下 可见能在window里拿到这个abc了  

同理  如果我要是想拿process的话

渲染进程像主进程通信(单向)

概述:在渲染进程中 ipcRenderer.send发送消息 ,在主进程中使用ipcMain.on接收消息

常用于  在web中使用主进程的API,例如下边这个需求

点击按钮 在用户的D盘创建一个hello.text文件  文件内容来自于用户输入

看下效果:

是可以拿到输入的值的  那么怎么传给主进程呢 敲重点!!!

预加载脚本引入ipcRenderer .send使用

javascript">console.log("preload", process.version);
const { contextBridge,ipcRenderer } = require("electron");
contextBridge.exposeInMainWorld("myAPI", {process: process.version,saveFile:(data)=>{ipcRenderer.send('file-save',data)}
});

渲染进程点击按钮传值

javascript">const btn1 = document.getElementById("btn1");
const btn2 = document.getElementById("btn2");
const input = document.getElementById("input");
console.log("render");btn1.onclick = () => {alert(window.myAPI.process);
};btn2.onclick = () => {
myAPI.saveFile(input.value)
};

主进程使用 ipcMain.on接收

javascript">const { app, BrowserWindow,ipcMain } = require("electron");
const path = require("path");
const fs=require('fs')function writeFile(event,data){fs.writeFileSync('D://hello.text',data)}
const createWindow = () => {const win = new BrowserWindow({width: 800,height: 600,autoHideMenuBar: true,webPreferences: {preload: path.resolve(__dirname, "./preload.js"),},});ipcMain.on("file-save",writeFile);win.loadFile("./pages/index.html");
};
// app.whenReady().then(() => {
//   createWindow();// });
app.on("ready", () => {createWindow();app.on("activate", () => {if (BrowserWindow.getAllWindows().length === 0) createWindow();});
});app.on("window-all-closed", () => {if (process.platform !== "darwin") app.quit();
});

画一下重点

然后运行下npm start 

 

总结下  就是在preload里边使用ipcRenderer.send方法然后render里边点击按钮调用这个方法然后在主进程里边使用 ipcMain.on进行接收  然后进行操作

渲染进程和主进程双向通信怎么通信呢(双向) 

例子:读取D盘里边hello.text

预加载里边写一个方法readFile 用invoke

javascript">console.log("preload", process.version);
const { contextBridge, ipcRenderer } = require("electron");
contextBridge.exposeInMainWorld("myAPI", {process: process.version,saveFile: (data) => {ipcRenderer.send("file-save", data);},readFile: () => {return  ipcRenderer.invoke("file-read");},
});

然后html里边写个按钮 读取hello.text

javascript"><!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><!-- https://web.nodejs.cn/en-US/docs/Web/HTTP/CSP --><meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'"><title>Hello World!</title><link rel="stylesheet" href="./index.css">
</head><body><button id="btn3" >读取D盘中的hello.text</button><script  src="./render.js"></script>
</body></html>

render.js里编写 调用预加载脚本的方法

javascript">
const btn3 = document.getElementById("btn3");btn3.onclick =() => {
myAPI.readFile();
};

然后主进程使用 ipcMain.handle进行接收

javascript">const { app, BrowserWindow, ipcMain } = require("electron");
const path = require("path");
const fs = require("fs");function writeFile(event, data) {fs.writeFileSync("D://hello.text", data);
}
// readFile;
function readFile() {let res = fs.readFileSync("D://hello.text").toLocaleString();console.log(res, "res");return res
}
const createWindow = () => {const win = new BrowserWindow({width: 800,height: 600,autoHideMenuBar: true,webPreferences: {preload: path.resolve(__dirname, "./preload.js"),},});ipcMain.on("file-save", writeFile);ipcMain.handle("file-read", readFile);win.loadFile("./pages/index.html");
};
// app.whenReady().then(() => {
//   createWindow();// });
app.on("ready", () => {createWindow();app.on("activate", () => {if (BrowserWindow.getAllWindows().length === 0) createWindow();});
});app.on("window-all-closed", () => {if (process.platform !== "darwin") app.quit();
});

划重点

读取完毕之后 需要返回给预加载脚本 用return 预加载脚本也直接return  然后就是render里边进行接收

因为是异步 所以接收到的是个pending状态 我们用await来接收下

就可以拿到了   总结下  就是在preload里边使用ipcRenderer.invoke方法然后render里边点击按钮调用这个方法然后在主进程里边使用 ipcMain.handle进行接收  接收完之后要使用render给他return出去 在预加载脚本里边也要return出去 然后在render.js里边使用async和await进行接收就行了


http://www.ppmy.cn/embedded/56089.html

相关文章

【云原生】MiniKube部署Kubernetes最小化集群

MiniKube安装Kubernetes集群&#xff08;一步到位&#xff09; 文章目录 MiniKube安装Kubernetes集群&#xff08;一步到位&#xff09;资源列表基础环境一、环境配置1.1、更新系统1.2、安装Docker1.3、配置Docker加速器 二、部署MiniKube2.1、安装kubectl2.2、安装MiniKube2.2…

cJSON源码解析之cJSON_Print函数

文章目录 前言cJSON_Print是干什么的cJSON_Print源码解析cJSON_Print函数实现print函数函数实现print_value函数update_offset函数 总结 前言 在处理JSON数据时&#xff0c;我们经常需要将内存中的JSON对象转换为字符串&#xff0c;以便于存储或传输。在C语言的cJSON库中&…

【Docker】docker 替换宿主与容器的映射端口和文件路径

every blog every motto: You can do more than you think. https://blog.csdn.net/weixin_39190382?typeblog 0. 前言 docker 替换宿主与容器的映射端口和文件夹 1. 正文 1.1 关闭docker 服务 systemctl stop docker1.2 找到容器的配置文件 cd /var/lib/docker/contain…

基于深度学习的人脸关键点检测

1. 任务和目标 人脸关键点检测的主要任务是识别并定位人脸图像中的特定关键点&#xff0c;例如眼睛的角点、眉毛的顶点、鼻子的底端、嘴角等。这些关键点不仅能提供面部结构的几何信息&#xff0c;还可以用于分析表情、识别个体&#xff0c;甚至检测面部姿势。 2. 技术和方法…

Build a Large Language Model (From Scratch)第五章(gpt-4o翻译版)

来源&#xff1a;https://github.com/rasbt/LLMs-from-scratch?tabreadme-ov-file https://www.manning.com/books/build-a-large-language-model-from-scratch

王者荣耀对折叠机进行专门适配优化,折叠机用户喜提加强

王者荣耀针对折叠屏手机做了针对性的适配优化&#xff0c;把折叠机的大屏幕优势发挥了出来——适配之后&#xff0c;用折叠屏玩王者荣耀拥有了更大的视野、以及更大的触控响应区域。 【更贴合折叠屏的视野适配】 此前王者荣耀并没有对折叠屏进行专门的适配&#xff0c;表现到…

网络爬虫详解

前言 网络爬虫&#xff08;Web Scraper&#xff09;是一种自动化程序&#xff0c;用于从互联网上提取数据。它们在数据采集、数据分析、市场调研等领域有着广泛的应用。本文将详细介绍网络爬虫的原理、工具、技术和最佳实践&#xff0c;帮助初学者和专业人士更好地理解和使用网…

CSRF是什么攻击 该如何解决

CSRF是什么攻击 CSRF&#xff08;Cross-Site Request Forgery&#xff09;&#xff0c;即跨站请求伪造攻击&#xff0c;也被称为“one-click attack”或“session riding”。它是一种网络攻击方式&#xff0c;利用已认证用户在受信任网站上的身份&#xff0c;诱使用户在不知情…