禹神electron学习~

最近时间比较富裕  咱们浅浅来学习下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.mfbz.cn/a/753208.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

人工智能期末复习思维导图,参考人工智能及其应用(第6版)和柴玉梅老师教材

其中第一、六、七、八、九章不用重点看&#xff0c;计算题一般会考1.语义网络、谓词逻辑&#xff0c;2.可信度&#xff0c;3.主观贝叶斯&#xff0c;4.一般合一置换&#xff0c;5.证据理论&#xff0c;6.盲目搜索。 第一章&#xff1a;绪论 第二章&#xff1a;知识表示方法 第…

MQ - RabbitMQ、SpringAMQP --学习笔记

什么是MQ&#xff1f; MQ 是消息队列&#xff08;Message Queue&#xff09;的缩写&#xff0c;它是一种应用程序间异步通信的技术。消息队列允许应用程序或服务间通过发送消息来交换数据&#xff0c;而不是直接调用对方&#xff0c;从而实现解耦、异步处理和负载均衡等目的。…

无需高配置 怎么获得超流畅的VR体验?

传统VR眼镜在使用中存在一些显著不足&#xff0c;而实时渲染技术又是如何解决的&#xff1f;接下来与大家共同探讨遇到的问题以及实时渲染在VR眼镜中的实际应用。 1、高配置要求 目前主流VR一体机的眼镜需要较高配置才能运行普通VR内容&#xff0c;且受限于VR眼镜的算力限制&…

工作纪实51-手撸AB实验分流策略

前几天写了一篇关于哈希算法的文章&#xff0c;起源就是在构思AB实验平台的时候&#xff0c;用到了哈希&#xff0c;所以对其做了深入的了解 AB实验平台是一般互联网做策略、样式实验会用到的一个系统&#xff0c;一般开启某个实验之后&#xff0c;需要对线上流量进行分流&…

太速科技-FMC144 -八路 250MSPS 14bit AD FMC子卡

FMC144 -八路 250MSPS 14bit AD FMC子卡 一、板卡概述   FMC144是一款具有8通道模数转换器&#xff08;ADC&#xff09;的FMC卡&#xff0c;具有14bit分辨率&#xff0c;最大采样速率达250Msps。时钟配置芯片为AD9516-1&#xff0c;可由板载10MHz时钟提供参考&#xff0c;也可…

[游戏开发][UE5]引擎学习记录

C Log和蓝图Log C Log 方法 UE_Log(参数1&#xff0c;参数2&#xff0c;参数3) //举例: UE_LOG(LogTemp, Error, TEXT("Log Info: %s"),"Test Log"); 三个参数的作用 参数1&#xff1a;输出窗口归类使用&#xff0c;你写什么它就显示什么 参数2&#x…

node.js安装

下载地址 https://nodejs.org/en/download 安装教程

Stable Diffusion初体验——提示词指南

前言 Stable Diffusion是一种深度学习模型&#xff0c;它能够根据提示词生成高质量的图像。在Stable Diffusion模型中&#xff0c;提示词起着至关重要的作用&#xff0c;因为它们为模型提供了关于所需输出的指导。本文将探讨Stable Diffusion关于提示词的原理&#xff0c;包括…

k8s集群node节点加入失败

出现这种情况&#xff1a; [preflight] FYI: You can look at this config file with kubectl -n kube-system get cm kubeadm-config -o yaml [kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml" [kubelet-start] Writing kub…

计算机网络——数据链路层(数据链路层概述及基本问题)

链路、数据链路和帧的概念 数据链路层在物理层提供服务的基础上向网络层提供服务&#xff0c;其主要作用是加强物理层传输原始比特流的功能&#xff0c;将物理层提供的可能出错的物理连接改造为逻辑上无差错的数据链路&#xff0c;使之对网络层表现为一条无差错的链路。 链路(…

sheng的学习笔记-AI-K均值算法

ai目录&#xff1a;sheng的学习笔记-AI目录-CSDN博客 需要学习前置知识&#xff1a;聚类&#xff0c;可参考 sheng的学习笔记-聚类(Clustering)-CSDN博客 目录 什么是k均值算法 流程 伪代码 数据集 伪代码 代码解释 划分示意图 优化目标 随机初始化 选择聚类数…

酣客的“FFC模式”|白酒商业模式|分润制度顶层架构设计

酣客公社摒弃传统商业模式&#xff0c;提出“心联网”及“FFC模式”的商业模式。 坐标&#xff1a;厦门&#xff0c;我是肖琳 深耕社交新零售行业10年&#xff0c;主要提供新零售系统工具及顶层商业模式设计、全案策划运营陪跑等。 今天和大家分享“酣客”的营销模式&#xff…

Parallels Toolbox for mac(pd工具箱) 6.0.2激活版

Parallels Toolbox 是由 Parallels 公司开发的一款实用工具集合软件&#xff0c;它主要面向使用 Parallels Desktop 的用户&#xff0c;提供了许多方便用户在 macOS 和 Windows 之间进行切换和管理的工具。Parallels Desktop 是一款流行的虚拟化软件&#xff0c;允许用户在 mac…

【24医学顶刊】GANDALF:主动学习 + 图注意力变换器 + 变分自编码器,改善多标签图像分类

GANDALF&#xff1a;主动学习 图注意力变换器 变分自编码器&#xff0c;改善多标签图像分类 提出背景子解法1&#xff1a;多标签信息样本的选择子解法2&#xff1a;生成信息丰富且非冗余的合成样本 例子&#xff1a;胸部X射线图像分析传统方法的操作和局限GaNDLF方法的优势 工…

理解ABP的领域驱动设计

大家好&#xff0c;我是张飞洪&#xff0c;感谢您的阅读&#xff0c;我会不定期和你分享学习心得&#xff0c;希望我的文章能成为你成长路上的垫脚石&#xff0c;让我们一起精进。 关于玩转ABP框架相关的文章&#xff0c;之前在博客园陆续写了《ABP vNext系列文章和视频》&…

电路仿真王者之争:SmartEDA如何领跑业界,打破传统仿真软件格局?

在电子设计领域&#xff0c;电路仿真软件一直扮演着至关重要的角色。它们为工程师们提供了一个虚拟的实验室&#xff0c;可以在不耗费大量实际资源的情况下&#xff0c;进行电路设计、优化和测试。在众多电路仿真软件中&#xff0c;SmartEDA以其独特的优势&#xff0c;逐渐崭露…

嵌入式开发十九:SysTick—系统定时器

在前面实验中我们使用到的延时都是通过SysTick进行延时的。 我们知道&#xff0c;延时有两种方式&#xff1a;软件延时&#xff0c;即CPU 循环等待产生的&#xff0c;这个延时是不精确的。第二种就是滴答定时器延时&#xff0c;本篇博客就来介绍 STM32F4 内部 SysTick 系统定时…

浅谈API生态建设:API安全策略的6项原则

API作为连接系统与应用的桥梁&#xff0c;在助力实现高效业务流程的同时&#xff0c;也不可避免出现资产管理困难、敏感数据泄漏风险骤增等安全问题。前段时间&#xff0c;安全公司Fastly公布了一项重磅调查报告&#xff0c;报告中显示95%的企业在过去1年中遭遇过API安全问题。…

AXI接口简介

AXI接口&#xff0c;全称为Advanced eXtensible Interface&#xff0c;是ARM公司推出的一种高性能、低成本、可扩展的高速总线接口。AXI接口是ARM公司提出的AMBA&#xff08;Advanced Microcontroller Bus Architecture&#xff09;高级微控制器总线架构的一部分。2003年发布了…

简易电阻、电容和电感测量仪-FPGA

通过VHDL语言编写程序用于设计电阻、电容和电感测量仪&#xff0c;通过使用试验箱进行验证是否设计正确&#xff0c;资料获取到咸&#x1f41f;&#xff1a;xy591215295250 \\\或者联系wechat 号&#xff1a;comprehensivable 设计并制作--台数字显示的电阻、电容和电感参数测试…