Electron入门笔记
Electron入门笔记
- Electron
- Electron 是什么
- Electron流程模型
- 创建第一个Electron项目
- 配置自动重启
- 主进程和渲染进程通信
- 打包应用
Electron
Electron 是什么
- 跨平台的桌面应用开发框架
- 使用 JavaScript、HTML 和 CSS 构建桌面应用程序的框架。 嵌入 Chromium和 Node.js
Electron流程模型
-
主进程:
- 主进程只有一个
- 主要功能是管理渲染进程,与操作系统打交道。调用Native API 进行各种系统级的操作,并且可以跨平台
- node环境,能使用node的各种API,使用node的各个模块进行操作,没有浏览器相关的属性,无法访问window等浏览器属性
渲染进程:
-
渲染进程有多个
-
主要是程序的展示的窗口
-
浏览器环境,本质就是Chromium,能使用浏览器的各种API,无法使用node环境的API(
ctrl shift i
可以打开窗口的控制台,跟浏览器是一模一样的,ctrl R
可以刷新页面)
-
主进程和渲染进程是可以通信的,可以是渲染进程向主进程单向通信,也可以是主进程想渲染进程通信,也可以双向通信,进程间的通信称为IPC
-
总结:主进程(一个)管理各个渲染进程(多个),渲染进程跟主进程进行通信(渲染进程间无法直接通信,通过主进程作为中间人可以实现),主进程调用各种Native API 完成系统级操作
创建第一个Electron项目
-
环境:需要先安装Node.js
- 注意:先安装Node.js只是为了正确安装
electron
, 因为 Electron 将 Node.js 嵌入到其二进制文件中,你应用运行时的 Node.js 版本与你系统中运行的 Node.js 版本无关
- 注意:先安装Node.js只是为了正确安装
-
mkdir my-electron-app && cd my-electron-app yarn init
-
执行
yarn init
生成package.json
后author
和description
在打包阶段属于必填项 -
{"name": "electron-first","version": "1.0.0","main": "main.js","license": "MIT","author": "XiaoMing","description": "Hello World", }
-
安装
Electron
并在package.json
配置启动命令-
yarn add ELectron -D
-
{"scripts": {"start": "electron ." // 注意 . 不能省略} }
-
启动项目前需要创建主进程,也就是
package.json
中对应的main
,命名为main.js
, 否则会报错,创建完成后,执行yarn start
即可启动 -
此时启动无报错,但也无任何反应,因为没有在主进程里配置任何东西,渲染窗口等进程需要在主进程中配置
-
-
创建
pages
文件夹用于存放页面文件(也就是渲染进程的文件),分别创建对应的index.html
,index.css
,render.js
文件-
在
index.html
中引入css
和js
文件 -
html
的head
需要配置一个meta
,解决CSP的警官-
<metahttp-equiv="Content-Security-Policy"content="default-src 'self'; script-src 'self' 'unsafe-inline'" />
-
-
-
-
default-src 'self'
是一组配置,意思是如果不做出任何的说明,引入的外部资源,只能是属于同源
script-src 'self' 'unsafe-inline'
是另一组配置,指引入样式的时候,可以有两种写法,第一种写法
self
是可以引入同源的样式表,第二种写法unsafe-inline
可以使用行内样式
-
-
<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8" /><!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP --><metahttp-equiv="Content-Security-Policy"content="default-src 'self'; script-src 'self' 'unsafe-inline'"/><title>Hello World!</title><link rel="stylesheet" href="./index.css" /></head><body><h1>Hello World!</h1>We are using Node.js <span id="node-version"></span>, Chromium<span id="chrome-version"></span>, and Electron<span id="electron-version"></span>.<script src="./render.js"></script></body> </html>
需要将写好的页面加载出来,如何加载页面,这个需要主进程进行控制,因此需要配置主进程main.js
-
const { app, BrowserWindow } = require("electron");const createWindow = () => {const win = new BrowserWindow({width: 800,height: 600,});win.loadFile("./pages/index.html"); };// app.whenReady().then(() => {}) 的写法与 app.on("ready", () =>{}) 同理app.on("ready", () => {createWindow();app.on("window-all-closed", () => {if (process.platform !== "darwin") app.quit();}); });
-
管理窗口的生命周期
-
关闭所有窗口时退出应用 (Windows & Linux),在Windows和Linux上,关闭所有窗口通常会完全退出一个应用程序。
// 为了实现这一点,你需要监听 app 模块的 'window-all-closed' 事件。如果用户不是在 macOS(darwin) 上运行程序,则调用 app.quit()。 app.on('window-all-closed', () => {if (process.platform !== 'darwin') app.quit() })
-
如果没有窗口打开则打开一个窗口 (macOS),macOS 应用通常即使在没有打开任何窗口的情况下也继续运行,并且在没有窗口可用的情况下激活应用时会打开新的窗口。
// 为了实现这一特性,监听 app 模块的 activate 事件。如果没有任何浏览器窗口是打开的,则调用 createWindow() 方法。 // 因为窗口无法在 ready 事件前创建,你应当在你的应用初始化后仅监听 activate 事件。 通过在您现有的 whenReady() 回调中附上您的事件监听器来完成这个操作。app.on("ready", () => {createWindow();app.on('activate', () => {if (BrowserWindow.getAllWindows().length === 0) createWindow()}) });
-
-
完整项目结构
-
启动项目
yarn start
配置自动重启
-
主进程每修改一次就得手动重启一次,可以配置自动重启
-
安装
nodemon
-
yarn add nodemon -D
-
-
更改启动命令
-
{"scripts": {"start": " nodemon --exec electron ."}, }
-
-
更改完启动命令发现自动重启的是主进程,但不改主进程,只改页面,发现页面窗口是需要手动刷新的,配置一个nodemon.json即可实现页面文件也能自动刷新
-
{"ignore": ["node_modules", "dist"],"restartable": "r","watch": ["*.*"],"ext": "html, css, js" }
-
主进程和渲染进程通信
-
目前主进程和渲染进程是没有什么关联的,主进程只是配置了加载渲染进程,然后他们之前没有其他的关系了,此时如果需要在渲染进程里拿到主进程中的node版本号是不可行的,因为渲染进程是浏览器环境,没有
process
属性 -
此时就需要一个预加载脚本作为主进程和渲染进程之间通信的桥梁,注意:预加载脚本可以拿到部分的node API,但不是所有
-
主进程目录下创建
preload.js
-
const { contextBridge } = require("electron");contextBridge.exposeInMainWorld("api", {version: process.version, });
-
-
主进程需要配置运行预加载脚本
-
const createWindow = () => {const win = new BrowserWindow({width: 800,height: 600,webPreferences: {preload: path.resolve(__dirname, "./preload.js"),},});win.loadFile("./pages/index.html"); };
-
-
配置一下渲染进程的脚本
-
const nodeVersion = document.querySelector("#node-version");console.log(window);nodeVersion.textContent = api.version;
-
-
最后结果
-
由此,引出,渲染进程跟主进程之间的相互通信,需要通过预加载脚本,因为预加载脚本也只能访问到node部分属性,像是文件操作等还是需要主进程来完成的
-
完成在窗口输入内容,并写入文件,最近将文件读出来的需求即可完全理解进程间的通信
-
main.js
-
const { app, BrowserWindow, ipcMain } = require("electron"); const path = require("path"); const fs = require("fs");const writeFile = (_, data) => {fs.writeFileSync(path.resolve(__dirname, "./hello.txt"), data); };const readFile = () => {return fs.readFileSync(path.resolve(__dirname, "./hello.txt")).toString(); };const createWindow = () => {const win = new BrowserWindow({width: 800,height: 600,webPreferences: {preload: path.resolve(__dirname, "./preload.js"),},});ipcMain.on("write-file", writeFile);ipcMain.handle("read-file", readFile);win.loadFile("./pages/index.html"); };app.on("ready", () => {createWindow();app.on("activate", () => {if (BrowserWindow.getAllWindows().length === 0) createWindow();}); });app.on("window-all-closed", () => {if (process.platform !== "darwin") app.quit(); });
-
-
preload.js
-
const { contextBridge, ipcRenderer } = require("electron");contextBridge.exposeInMainWorld("api", {version: process.version,writeFile: (data) => {ipcRenderer.send("write-file", data);},readFile: () => ipcRenderer.invoke("read-file"), });
-
-
render.js
-
const nodeVersion = document.querySelector("#node-version"); const input = document.querySelector("#input"); const write = document.querySelector("#write"); const read = document.querySelector("#read");nodeVersion.textContent = api.version;window.onload = () => {write.addEventListener("click", () => {api.writeFile(input.value);});read.addEventListener("click", async () => {const text = await api.readFile();alert(text);}); };
-
-
index.html
-
<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8" /><!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP --><metahttp-equiv="Content-Security-Policy"content="default-src 'self'; script-src 'self' 'unsafe-inline'"/><title>Hello World!</title><link rel="stylesheet" href="./index.css" /></head><body><h1>Hello World!</h1>We are using Node.js <span id="node-version"></span>, Chromium<span id="chrome-version"></span>, and Electron<span id="electron-version"></span>.<hr /><input id="input" /><button id="write">写入文件</button><button id="read">读取文件</button><script src="./render.js"></script></body> </html>
-
打包应用
-
使用
electron build
打包成一个安装包应用 -
yarn add electron-build -D
-
electron-build
配置地址:CodeBlog/Electron/electron-builder打包详解.md at master · QDMarkMan/CodeBlog (github.com) -
配置
package.json
-
{"scripts": {"build": "electron-builder"},"build": {"appId": "com.electron.myapp","nsis": {"oneClick": false,"allowElevation": true,"allowToChangeInstallationDirectory": true},"win": {"icon": "./vite.svg","target": [{"target": "nsis","arch": ["x64"]}]}} }
-
-
electron-builder打包慢解决方法
- electron-builder 打包太慢解决方法build过程耗时较长,可以手动下载部分文件。镜像地址 https:/ - 掘金 (juejin.cn)
相关文章:

Electron入门笔记
Electron入门笔记 ElectronElectron 是什么Electron流程模型创建第一个Electron项目配置自动重启主进程和渲染进程通信打包应用 Electron Electron 是什么 跨平台的桌面应用开发框架使用 JavaScript、HTML 和 CSS 构建桌面应用程序的框架。 嵌入 Chromium和 Node.js Electro…...

python 不相交集简介(并查集算法)【Introduction to Disjoint Set (Union-Find Algorithm)】
什么是不相交集数据结构? 如果两个集合没有任何共同元素,则它们被称为不相交集,集合的交集为空集。 存储不重叠或不相交元素子集的数据结构称为不相交集合数据结构。不相交集合数据结构支持以下操作: 1、将新集合添加到不相交集合…...

23种设计模式之工厂方法模式
文章目录 1. 简介2. 代码2.1 抽象类:Course.java2.2 产品A:JavaCourse.java2.3 产品B:PythonCourse.java2.4 工厂抽象类:CourseFactory.java2.5 产品A的工厂A:JavaCourseFactory.java2.6 产品B的工厂B:PyCo…...

Redis——事务
文章目录 Redis 事务Redis 的事务和 MySQL 事务的区别:事务操作MULTIEXECDISCARDWATCHUNWATCHwatch的实现原理 总结 Redis 事务 什么是事务 Redis 的事务和 MySQL 的事务 概念上是类似的. 都是把⼀系列操作绑定成⼀组. 让这⼀组能够批量执行 Redis 的事务和 MySQL 事务的区别:…...
Redis非关系型数据库操作命令大全
以下是 Redis 的常用操作命令大全,涵盖了键值操作、字符串、哈希、列表、集合、有序集合、发布/订阅、事务等多个方面的操作。 1. 通用键命令 命令说明SET key value设置指定 key 的值GET key获取指定 key 的值DEL key删除指定的 keyEXISTS key检查 key 是否存在E…...

基于SpringBoot+Vue+uniapp微信小程序的澡堂预订的微信小程序的详细设计和实现
项目运行截图 技术框架 后端采用SpringBoot框架 Spring Boot 是一个用于快速开发基于 Spring 框架的应用程序的开源框架。它采用约定大于配置的理念,提供了一套默认的配置,让开发者可以更专注于业务逻辑而不是配置文件。Spring Boot 通过自动化配置和约…...

Linux mips架构链接库函数调用plt表汇编代码分析
linux调用共享库中的函数时通过plt表和got表实现位置无关代码,过程中涉及到lazy binding,即在第一调用外部函数时解析被调用的函数地址并将地址写入到got表,后续调用则不需要解析函数地址。这一部分和硬件架构有关,具体的是和cpu指…...

python 作业1
任务1: python为主的工作是很少的 学习的python的优势在于制作工具,制作合适的工具可以提高我们在工作中的工作效率的工具 提高我们的竞争优势。 任务2: 不换行 换行 任务3: 安装pycharm 进入相应网站Download PyCharm: The Python IDE for data science and we…...
Apache 出现 “403 forbidden“ 排查方法
1、检查运行 Apache 进程的用户没有对目录具备读取权限 如果该用户没有对 Directory 指定的目录具备适当的读取权限,就会导致 403 错误。 例如:使用用户apache启动Apache进程,但是apache用户对 Directory 指定的目录没有读取权限 2、检查…...
vue video播放m3u8监控视频
很关键的问题 vite创建的项目不需要import ‘videojs-contrib-hls’ 导入就报错 直接添加如下代码即可 html5: {vhs: {overrideNative: true},nativeVideoTracks: false,nativeAudioTracks: false,nativeTextTracks: false} 下面是完整组件示例 <template><div>…...

uniapp 获取签名证书 SHA1 自有证书签名打包
1.登录你的Dcloud 账户 2.找到我的应用菜单 3.点开某个应用 4.查看证书详情,里面有SHA1 和别名,密码,下载证书用于云打包,可以选择自有证书,输入别名,密码打包...
Open3d开发点云标注工具问题总结(二)
前面我们介绍了使用AABB方式来框选点云,但这种方式还是不够直观,我们的构想是设计一个和o3d.visualization.VisualizerWithEditing的点云框选方法一样的软件,因此,博主想到利用投影的形式进行解决: 具体的,…...

【FreeRTOS】
报错: 使用STM32cubemx自动生成freertos选项V2报错,V1不报错 …/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/freertos_os2.h(31): 解决 修改cubemx配置,将V1.8.6改选为V1.8.5后编译不再报错...
洛谷 P4995:跳跳! ← 贪心算法
【题目来源】https://www.luogu.com.cn/problem/P4995【题目描述】你是一只小跳蛙,你特别擅长在各种地方跳来跳去。 这一天,你和朋友小 F 一起出去玩耍的时候,遇到了一堆高矮不同的石头,其中第 i 块的石头高度为 hi,地…...

代理 IP 在 AI 爬虫中的关键应用
现如今,人工智能(AI)的发展日新月异,而数据作为驱动 AI 发展的关键要素,其重要性不言而喻。AI 爬虫作为获取大量数据的重要工具,在数据收集过程中发挥着至关重要的作用。而代理 IP 在 AI 爬虫中有着广泛而重…...

【Vercel】Vercel静态部署踩坑
背景 在现代的软件开发中,自动化部署是一个不可或缺的环节。Vercel作为一个流行的前端部署平台,提供了与GitHub的无缝集成,使得开发者能够在每次提交代码后自动触发部署流程。然而,自动化部署过程中可能会遇到一些挑战࿰…...

【Spring】关于Spring中aware相关接口的作用
Aware 接口的回调方法是在 Bean 实例化之后调用的。具体来说,这些回调方法是在依赖注入完成后,但在 Bean 完全初始化之前调用的。这是 Spring 容器管理 Bean 生命周期的一部分 完成了属性赋值之后,Spring会执行一些回调,包括&…...

动态内存管理及RAII的简单应用
目录 一.程序启动所关联的内存分区 二.动态内存的申请和释放 三.将RAII思想融入代码 四.RAII思想的简单应用 一.程序启动所关联的内存分区 .dll文件是Dynamic Link Library(动态链接库)文件的缩写,它是一种共享库文件,包含…...

7、Vue2(一)
1.认识Vue 官网地址:https://v2.cn.vuejs.org/v2/guide/ Vue.js 是一套构建用户界面的渐进式框架。 Vue 2 是在2016年发布使用,2020是 vue3 才刚发布,时隔一年左右就已经将 vue3 作为了默认版本 尤雨溪,Vue.js和Vite的作者&…...
Chapter11
11.3 #include <stdio.h> #include <string.h> #define NUM_STUDENTS 40 #define NUM_SUBJECTS 3 // 学生结构体 typedef struct { int id; char name[50]; float scores[NUM_SUBJECTS]; float average; } Student; void inputData(Student studen…...
DockerHub与私有镜像仓库在容器化中的应用与管理
哈喽,大家好,我是左手python! Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库,用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...

Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...

自然语言处理——循环神经网络
自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元(GRU)长短期记忆神经网络(LSTM)…...

SpringTask-03.入门案例
一.入门案例 启动类: package com.sky;import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCach…...
今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存
文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...
管理学院权限管理系统开发总结
文章目录 🎓 管理学院权限管理系统开发总结 - 现代化Web应用实践之路📝 项目概述🏗️ 技术架构设计后端技术栈前端技术栈 💡 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 🗄️ 数据库设…...

LabVIEW双光子成像系统技术
双光子成像技术的核心特性 双光子成像通过双低能量光子协同激发机制,展现出显著的技术优势: 深层组织穿透能力:适用于活体组织深度成像 高分辨率观测性能:满足微观结构的精细研究需求 低光毒性特点:减少对样本的损伤…...
WebRTC从入门到实践 - 零基础教程
WebRTC从入门到实践 - 零基础教程 目录 WebRTC简介 基础概念 工作原理 开发环境搭建 基础实践 三个实战案例 常见问题解答 1. WebRTC简介 1.1 什么是WebRTC? WebRTC(Web Real-Time Communication)是一个支持网页浏览器进行实时语音…...
Linux系统部署KES
1、安装准备 1.版本说明V008R006C009B0014 V008:是version产品的大版本。 R006:是release产品特性版本。 C009:是通用版 B0014:是build开发过程中的构建版本2.硬件要求 #安全版和企业版 内存:1GB 以上 硬盘…...