禹神electron学习~

news2024/12/23 6:03:56

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

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

 先看下流程模型

 先决条件

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

创建你的应用

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

搭建项目脚手架

然后打开vscode

npm init

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

  • entry point 应该是 main.js

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

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

{
  "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 中。 

npm install --save-dev electron

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

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

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

npm start

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

运行主进程 

 

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

 创建网页

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

<!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 文件的顶部:

 

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

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

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")来  此处我喜欢用后者  因为他俩是一样的  用哪个无所谓哈

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()。

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

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

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

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

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

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

效果是这样的

 

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

render.js与index。html的交互

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需要加上这段代码

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

然后npm start运行下

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

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

打印出来了   

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

需要个属性

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使用

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

渲染进程点击按钮传值

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接收

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

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

<!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里编写 调用预加载脚本的方法


const btn3 = document.getElementById("btn3");



btn3.onclick =() => {
myAPI.readFile();
};

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

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.coloradmin.cn/o/1883996.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

在Zotero中使用Deepl翻译

文章目录 Zotero简介Zotero下载插件下载在Zotero中安装插件获取Deepl密钥在Zotero中使用deepl 参考链接 Zotero简介 Zotero是一款非常实用的文献管理软件&#xff0c;可以快速帮助我们下载、分类和标注文献。由于专业需要&#xff0c;很多使用者需要阅读外文文献&#xff0c;Z…

无锁编程——从CPU缓存一致性讲到内存模型(1)

一.前言 1.什么是有锁编程&#xff0c;什么是无锁编程&#xff1f; 在编程中&#xff0c;特别是在并发编程的上下文中&#xff0c;“无锁”和“有锁”是描述线程同步和资源访问控制的两种不同策略。有锁&#xff08;Locked&#xff09;: 有锁编程是指使用锁&#xff08;例如互…

Redis-分布式锁(基本原理和不同实现方式对比)

文章目录 1、基本原理2、不同实现方式 1、基本原理 分布式锁&#xff1a;满足分布式系统或集群模式下多进程可见并且互斥的锁。 分布式锁的核心思想就是让大家都使用同一把锁&#xff0c;只要大家使用的是同一把锁&#xff0c;那么我们就能锁住线程&#xff0c;不让线程进行&am…

Mysql 的账户管理,索引,存储引擎

目录 一.MySQL的账户管理 1.存放用户信息的表 2.查看当前使用的用户 3.新建用户 4.修改用户名称 5.删除用户 6.修改用户密码 7.破解密码 8. 远程登录 9.用户权限管理 9.1 权限类别 9.2 查看权限 9.3 授予权限 9.4 撤销权限 二.索引 1. 索引管理 1.1 查看索…

Generating Diverse Structure for Image Inpainting With Hierarchical VQ-VAE

Jialun Peng1 Dong Liu1* Songcen Xu2 Houqiang Li1 1 University of Science and Technology of China 2 Noahs Ark Lab, Huawei Technologies Co., Ltd.pjlmail.ustc.edu.cn, {dongeliu, lihq}ustc.edu.cn, xusongcenhuawei.com 原文提供代码链接&#xff1a; GitHub - UST…

MySQL:数据类型

数据类型 1. 字符串类型2. 整数类型3. 定点数类型和浮点数类型4. 布尔类型5. 枚举和集合类型6. 日期和时间类型7. Blob类型8. JSON类型 字符串类型、数字类型、日期和时间类型、存放二进制的数据类型、存放地理数据的类型。 1. 字符串类型 字符串类型也可以用来存储邮编&…

【论文阅读】-- 研究时间序列可视化,提升用户体验

Investigating Time Series Visualisations to Improve the User Experience 摘要1 引言2 相关工作互动技巧视觉编码坐标系 3 用户研究时间序列可视化互动技巧任务实验设计 4 结果交互技术的效果视觉编码的影响坐标系的影响 5 讨论交互技术的效果视觉编码的影响坐标系的影响 6 …

(必看图文)Hadoop集群安装及MapReduce应用(手把手详解版)

前言 随着大数据时代的到来&#xff0c;处理和分析海量数据已成为企业和科研机构不可或缺的能力。Hadoop&#xff0c;作为开源的分布式计算平台&#xff0c;因其强大的数据处理能力和良好的可扩展性&#xff0c;成为大数据处理领域的佼佼者。本图文教程旨在帮助读者理解Hadoop集…

《昇思25天学习打卡营第5天|数据变换 Transforms》

文章目录 前言&#xff1a;今日所学&#xff1a;1. Common Transforms2. Vision Transforms3. Text Transforms 前言&#xff1a; 我们知道在进行神经网络训练的时候&#xff0c;通常要将原始数据进行一系列的数据预处理操作才会进行训练&#xff0c;所以MindSpore提供了不同类…

C语言部分复习笔记

1. 指针和数组 数组指针 和 指针数组 int* p1[10]; // 指针数组int (*p2)[10]; // 数组指针 因为 [] 的优先级比 * 高&#xff0c;p先和 [] 结合说明p是一个数组&#xff0c;p先和*结合说明p是一个指针 括号保证p先和*结合&#xff0c;说明p是一个指针变量&#xff0c;然后指…

蒂升电梯职业性格和Verify认知能力SHL测评答题攻略及薪资待遇解密!

​一、蒂升电梯职业性格和认知能力测评考什么 您好&#xff01;蒂升电梯公司邀请您参加的OPQ职业性格测评和Verify认知能力测评是两种常见的评估工具&#xff0c;用于帮助了解个人的职场性格特点和认知能力。 OPQ职业性格测评 这是一种性格测试&#xff0c;通常用于评估个人在…

一文讲解Docker入门到精通

一、引入 1、什么是虚拟化 在计算机中&#xff0c;虚拟化&#xff08;英语&#xff1a;Virtualization&#xff09;是一种资源管理技术&#xff0c;它允许在一台物理机上创建多个独立的虚拟环境&#xff0c;这些环境被称为虚拟机&#xff08;VM&#xff09;。每个虚拟机都可以…

盘古5.0,靠什么去解最难的题?

文&#xff5c;周效敬 编&#xff5c;王一粟 当大模型的竞争开始拼落地&#xff0c;商业化在B端和C端都展开了自由生长。 在B端&#xff0c;借助云计算向千行万业扎根&#xff1b;在C端&#xff0c;通过软件App和智能终端快速迭代。 在华为&#xff0c;这家曾经以通信行业起…

Java登录管理功能的自我理解(尚庭公寓)

登录管理 背景知识 1. 认证方案概述 有两种常见的认证方案&#xff0c;分别是基于Session的认证和基于Token的认证&#xff0c;下面逐一进行介绍 基于Session 基于Session的认证流程如下图所示 该方案的特点 登录用户信息保存在服务端内存&#xff08;Session对象&#xff…

Django 一对多关系

1&#xff0c;创建 Django 应用 Test/app9 django-admin startapp app9 2&#xff0c;注册应用 Test/Test/settings.py 3&#xff0c;添加应用路由 Test/Test/urls.py from django.contrib import admin from django.urls import path, includeurlpatterns [path(admin/,…

安装KB5039212更新卡在25% 或者 96% 进度

系统之家7月1日消息&#xff0c;微软在6月11日的补丁星期二活动中&#xff0c;为Windows 11系统推出了KB5039212更新。然而&#xff0c;部分用户在Windows社区中反映&#xff0c;安装过程中出现失败&#xff0c;进度条在25%或96%时卡住。对于遇到此类问题的Windows 11用户&…

YOLOv8改进 | 主干网络 | C2f融合动态卷积模块ODConv

&#x1f4a1;&#x1f4a1;&#x1f4a1;本专栏所有程序均经过测试&#xff0c;可成功执行&#x1f4a1;&#x1f4a1;&#x1f4a1; 专栏目录 &#xff1a;《YOLOv8改进有效涨点》专栏介绍 & 专栏目录 | 目前已有40篇内容&#xff0c;内含各种Head检测头、损失函数Loss、…

Linux CentOS 7 离线安装.NET环境

下载 下载.NET 例如&#xff1a; aspnetcore-runtime-6.0.15-linux-x64.tar.gz 复制 复制到如下目录&#xff1a; /usr/local/dotnet/aspnetcore-runtime-6.0.15-linux-x64.tar.gz 解压 cd /usr/local/dotnet/ tar -zxvf aspnetcore-runtime-6.0.15-linux-x64.tar.gz 创建…

非标设备行业的数智化项目管理

近年来&#xff0c;中国制造快速发展&#xff0c;企业迫切需要加快转型升级。与传统制造业相比&#xff0c;高端制造业具有明显的优势&#xff1a;高技术、高附加值、低污染、低排放、竞争优势强。一方面&#xff0c;企业对于生产效率和自动化水平的要求不断提高&#xff0c;期…

esp12实现的网络时钟校准

网络时间的获取是通过向第三方服务器发送GET请求获取并解析出来的。 在本篇博客中&#xff0c;网络时间的获取是一种自动的行为&#xff0c;当系统成功连接WiFi获取到网络天气后&#xff0c;系统将自动获取并解析得到时间和日期&#xff0c;为了减少误差每两分钟左右进行一次校…