Electron快速上手

什么是Electron

  • 一款应用广泛的跨平台的桌面应用开发框架。
  • Electron的本质是结合了 Chromium 与Node.js。
  • 使用HTML、CSS、JS 等Web技术构建桌面应用程序。
    • .vue,.tsx,.less,.ts也可以使用

Electron 流程模型

  •  主进程是纯node环境,可以访问__dirname,fs模块等,不能访问alert(),window等
  • 渲染进程可以访问alert(),window等,不能访问__dirname,fs模块等
  • 一个主进程可以管理多个渲染进程,渲染进程能够与主进程沟通
  • 主进程可以调用原生api

创建应用程序

Electron 应用程序遵循与其他 Node.js 项目相同的结构。 首先创建一个文件夹并初始化 npm 包。

mkdir my-electron-app && cd my-electron-app
npm init

 init初始化命令会提示您在项目初始化配置中设置一些值 为本教程的目的,有几条规则需要遵循:

  • entry point 应为 main.js.
  • author 与 description 可为任意值,但对于应用打包是必填项。

你的 package.json 文件应该像这样:

{"name": "my-electron-app","version": "1.0.0","description": "Hello World!","main": "main.js","author": "Jane Doe","license": "MIT"
}

然后,将 electron 包安装到应用的开发依赖中。

npm install --save-dev electron

创建main.js

就可以通过npm start运行程序

简单程序制作

展示网页信息
//main.jsconst {app,BrowserWindow} = require('electron')app.on('ready',()=>{// 当app准备好的时候调用回调const win = new BrowserWindow({//创建窗口width:800,height:600,autoHideMenuBar:true,//隐藏默认配置菜单x:0,y:0,//在什么位置打开alwaysOnTop:true//一直置顶,不被遮挡})win.loadURL('https://blog.csdn.net/m0_56772756?type=blog')//加载远程页面
})
 展示个人页面
//html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><link rel="stylesheet" href="index.css">
</head>
<body><h1>学习electron开发</h1>
</body>
</html>//index.css
h1{background-color: aquamarine ;color: purple;
}
const {app,BrowserWindow} = require('electron')app.on('ready',()=>{// 当app准备好的时候调用回调const win = new BrowserWindow({//创建窗口width:800,height:600,autoHideMenuBar:true,//隐藏默认配置菜单x:0,y:0,//在什么位置打开alwaysOnTop:true//一直置顶,不被遮挡})// win.loadURL('http://www.atguigu.com')//加载页面// 加载文件win.loadFile('./pages/index.html')
})

 npm start执行程序

终端出现警告(可忽略)

内容安全策略

在页面中运行ctrl+shift+i查看开发者工具

 出现警告​​​​内容安全策略(CSP)给html文件添加meta标签,配置CSP(Content-Security-Policy)

    <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self';style-src 'self' 'unsafe-inline';img-src 'self' ">

部分配置说明

1. default-src  'self'

  • default-src:配置加载策略,适用于所有未在其它指令中明确指定的资源类型。
  • self:仅允许从同源的资源加载,禁止从不受信任的外部来源加载,提高安全性。

2. style-src  'self' ' unsafe-inline

  • style-src:指定样式表(CSS)的加载策略。
  • self:仅允许从同源的资源加载,禁止从不受信任的外部来源加载,提高安全性。
  • unsafe-inline :允许在HTML文档内使用内联样式。

3. img-src  'self'  data:

  • img-src:指定图像资源的加载策略。
  • self:表示仅允许从同源加载图像。
  • data::允许使用data: URI来嵌入图像。这种URI模式允许将图像数据直接嵌入到HTML或CSS中,而不是通过外部链接引用。

了解更多查看:​​​​内容安全策略(CSP)

完善窗口行为

1. Windows和Linux平台窗口特点是:关闭所有窗口时退出应用。

app.on('window-all-closed', () => {//当所有窗口都关闭的时候if (process.platform !== 'darwin') app.quit()//如果不是苹果系统Mac(darwin),退出应用
})

2. mac应用即使在没有打开任何窗口的情况下也继续运行,并且在没有窗口可用的情况下激活应用时会打开新的窗口。

//当app准备好后,执行createwindow创建窗口
app.on( 'ready' ,()=>{createwindow()//当应用被激活时app.on( 'activate', ()=>{//如果当前应用没有窗口,则创建一个新的窗口if (Browserwindow.getAllwindows().length === 0) createwindow()})
})

 更多窗口行为查看:BrowserWindow | Electron (electronjs.org)

配置自动重启
npm i nodemon -d

修改package.json配置

"start": "nodemon --exec electron ."

 此配置只实现了mian.js的修改触发自动重启,页面的修改不能实现自动重启

配置nodemon.json规则

{"'ignore":["node_modules","dist"],"restartable":"r","watch":["*.*"],"ext":"html,js,css"
}

 "restartable":"r",是配置短命令 ,在终端命令行中输入r实现程序自动重启

配置好以后,当代码修改后,应用就会自动重启了。

electron控制台打印乱码

修改package.json文件

  "start": "chcp 65001 && nodemon --exec electron ."

主进程与渲染进程

主进程与渲染进程个分隔开

主进程

每个Electron应用都有一个唯一的主进程,作为应用程序的入口点(main.js)。主进程在Node.js环境中运行,它具有require模块和使用所有Node.js API的能力,主进程的核心就是:使用BrowserWindow来创建和管理窗口。无法访问浏览器函数。

主进程(main.js)不能访问window、alert之类的

渲染进程

每个BrowserWindow实例都对应一个单独的渲染器进程(多个渲染进程),运行在渲染器进程中的代码,必须遵守网页标准,这也就意味着:渲染器进程无权直接访问require或使用任何Node.js的API

问题产生:处于渲染器进程的用户界面,该怎样才与Node.js和Electron的原生桌面功能进行交互呢?

Preload脚本

预加载(Preload)脚本是运行在渲染进程中的,但它是在网页内容加载之前执行的,这意味着它具有比普通渲染器代码更高的权限,可以访问Node.js的 API,同时又可以与网页内容进行安全的交互。
简单说:它是Node.jsWeb APl的桥梁,Preload 脚本可以安全地将部分Node.js功能暴露给网页,从而减少安全风险。

在渲染进程(浏览器环境)中中运行

需求:点击按钮后,在页面呈现当前的Node 版本。

preload.js文件不能直接触发,需要在main.js中定义

 执行顺序:主进程 -> 预加载脚本 -> 渲染进程 

prload可访问api
可用的 API详细信息
Electron 模块渲染进程模块
Node.js 模块events、timers、url
Polyfilled 的全局模块Buffer、process、clearImmediate、setImmediate
暴露Electron 的 process.versions 对象给渲染器
//预加载脚本 preload.js
const { contextBridge  } =require ('electron')console.log('preload')contextBridge.exposeInMainWorld('toRenderVersions',{//对外暴露一个toRenderVersions全局变量,是渲染进程可以获取node:()=>process.versions.node,//node版本chrome:()=>process.versions.chrome,electron:()=>process.versions.electron
})
//main.jsconst {app,BrowserWindow} = require('electron')
const path = require('node:path')//node的path方法function createWindow(){const win = new BrowserWindow({//创建窗口width:800,height:600,autoHideMenuBar:true,//隐藏默认配置菜单x:0,y:0,//在什么位置打开webPreferences:{// 网页功能设置preload:path.join(__dirname,'./preload.js')}})// 加载文件win.loadFile('./pages/index.html')
}app.on('ready',()=>{// 当app准备好的时候调用回调console.log('应用准备完毕!!!')createWindow()app.on('activate', () => {//应用被激活的时候(仅针对苹果系统)if (BrowserWindow.getAllWindows().length === 0) createWindow() // 当前窗口数量是0 ,没有窗口,就创建窗口})
})

这里使用了两个Node.js概念:

  • __dirname 字符串指向当前正在执行的脚本的路径(在本例中,它指向你的项目的根文件夹)。
  • path.join API 将多个路径联结在一起,创建一个跨平台的路径字符串。

现在渲染器能够全局访问 versions 了,让我们快快将里边的信息显示在窗口中。 这个变量不仅可以通过 window.versions 访问,也可以很简单地使用 versions 来访问。 新建一个 renderer.js 脚本, 使用 document.getElementById DOM API 来替换 id 属性为 info 的 HTML 元素的文本。

//render.js
// 执行在渲染进程中
const btn1 = document.getElementById('btn1')btn1.onclick = ()=>{alert('此应用的node版本'+toRenderVersions.node()+'chrome版本'+toRenderVersions.chrome()+'electron版本'+toRenderVersions.electron())
}

进程之间通信(IPC)

1. 渲染进程->主进程(单向)

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

常用于:在 Web中调用主进程的API,例如下面的这个需求:

需求:点击按钮后,在用户的D盘创建一个hello.txt文件,文件内容来自于用户输入。

1.页面中添加相关元素,render.js中添加对应脚本

    <input id="input" type="text"><button id="btn2"> 向d盘写入hello.txt</button>
const btn2=document.getElementById('btn2')
const input=document.getElementById('input')btn2.onclick=()=>{toRenderVersions.saveFile(input.value)
}

2. preload.js 中使用ipcRenderer.invoke('信道',参数)发送消息,与主进程通信。

//预加载脚本
const { contextBridge ,ipcRenderer } =require ('electron') contextBridge.exposeInMainWorld('toRenderVersions',{saveFile:(data)=>{// 传入参数:信道,数据ipcRenderer.send('file-save',data)}
})

3.主进程main.js使用ipcMain.on('信道',()=>{})收到消息,触发函数执行

const {app,BrowserWindow,ipcMain} = require('electron')function writeFile(_,data){fs.writeFileSync('D:/hello.txt',data)
}function createWindow(){const win = new BrowserWindow({//创建窗口width:800,height:600,autoHideMenuBar:true,//隐藏默认配置菜单webPreferences:{// 网页功能设置,web首选项preload:path.join(__dirname,'./preload.js')//绝对路径}})ipcMain.on('file-save',writeFile)//send对应onwin.loadFile('./pages/index.html')
}

2.主进程与渲染进程的双向通信

概述:渲染进程通过ipcRenderer.invoke 发送消停,主进程使用ipcMain.handle接收并处理消息。

备注:ipcRender.invoke的返回值是Promise实例

常用于:从渲染器进程调用主进程方法并等待结果,例如下面的这个需求:

需求:点击按钮从D盘读取hello.txt中的内容,并将结果呈现在页面上。

1.页面中添加相关元素,render.js中添加对应脚本

   <button id="btn3">读取D盘中的hello.txt</button>
const btn3=document.getElementById('btn3')
btn3.onclick=async()=>{let fileContent =await toRenderVersions.readFile()console.log(fileContent)alert(fileContent)
}

2. preload.js中使用ipcRenderer.invoke( '信道',参数)发送消息,与主进程通信。

//预加载脚本
const { contextBridge ,ipcRenderer } =require ('electron') contextBridge.exposeInMainWorld('toRenderVersions',{readFile:()=>{//传入参数:信道,(数据)return ipcRenderer.invoke('file-read')//调用,渲染进程与主进程的双向通信}
})

3.主进程main.js使用ipcMain.handle('信道',()=>{})接收消息,并执行函数返回数据

const {app,BrowserWindow,ipcMain} = require('electron')
const path = require('node:path')//node的path模块
const fs = require('fs')function readFile(){console.log( fs.readFileSync('D:/hello.txt'),fs.readFileSync('D:/hello.txt').toString())return fs.readFileSync('D:/hello.txt').toString()
}function createWindow(){const win = new BrowserWindow({//创建窗口width:800,height:600,autoHideMenuBar:true,//隐藏默认配置菜单webPreferences:{// 网页功能设置,web首选项preload:path.join(__dirname,'./preload.js')//绝对路径}})ipcMain.handle('file-read',readFile)//invoke对应handlewin.loadFile('./pages/index.html')
}

3.主进程->渲染进程(单项通信)

概述:主进程使用win.webContents.send发送消息,渲染进程通过ipcRenderer.on处理消息,

常用于:从主进程主动发送消息给渲染进程,例如下面的这个需求:

需求:应用加载6秒钟后,主动给渲染进程发送一个消息,内容是:你好啊!

1.页面中添加相关元素,render.js 中添加对应脚本

window.onload=()=>{toRenderVersions.getMessage(logMessage)
}const logMessage = (event,str)=>{console.log(event,str)
}

2.preload.js中使用ipcRenderer.on(‘信道’,回调)接收消息,并配置回调函数.

getMessage:(callback)=>{return ipcRenderer.on('message',callback)
}

3.主进程中,在合适的时候,使用win.webContents.send('信道',数据)发送消息。

// 加载了本地页面后,创建一个定时器
setTimeout(() => {win.webContents.send('message','你好啊')
}, 6000);

渲染进程与渲染进程之间不能直接通信,需要通过主进程传递数据

打包应用

使用electron-builder打包应用
1.安装electron-builder :

npm install electron-builder -D

2.在package.json中进行相关配置,具体配置如下

备注:json文件不支持注释,使用时请去掉所有注释。

{"name": "my-electron-app",//应用程序的名称"version": "1.0.0",//应用程序的版本"description": "my first electron app",//应用程序的描述"main": "main.js",//应用程序入口文件"scripts": {"start": "chcp 65001 && nodemon --exec electron .",//使用`electron .`命令启动应用程序"build":"electron-builder"//使用`electron-builder`打包应用程序,生成安装包},"build":{"appId":"com.ylx.hahaha",//应用程序唯一标识符//打包windows平台安装包的具体配置"win":{"icon":"./logo.ico",//应用图标"target":[{"target":"nsis",//指定使用 NSIS 作为安装程序格式(.exe安装包文件)"arch":["x64"]//生成64 位安装包}]},"nsis":{"oneClick":false,//设置为`false`使安装程序显示安装向导界面,而不是一键安装"perMachine":true,//允许每台机器安装一次,而不是每个用户都安装"allowToChangeInstallationDirectory":true//允许用户在安装过程中选择安装目录}},"author": "ylx",//作者信息"license": "ISC",//许可证信息"devDependencies": {"electron": "^32.0.1",//开发依赖中的Electron版本"electron-builder": "^24.13.3"//开发依赖中的‘electron-builder’版本},"dependencies": {"nodemon": "^3.1.4"}
}

执行打包命令:

npm run build

electron-vite

electron-vite 是一个新型构建工具,旨在为 Electron 提供更快、更精简的开发体验。它主要由五部分组成:

  • 一套构建指令,它使用 Vite 打包你的代码,并且它能够处理 Electron 的独特环境,包括 Node.js 和浏览器环境。

  • 集中配置主进程、渲染器和预加载脚本的 Vite 配置,并针对 Electron 的独特环境进行预配置。

  • 为渲染器提供快速模块热替换(HMR)支持,为主进程和预加载脚本提供热重载支持,极大地提高了开发效率。

  • 优化 Electron 主进程资源处理。

  • 使用 V8 字节码保护源代码。

electron-vite 需要 Node.js 版本 18+,20+ 和 Vite 版本 4.0+

更多electron-vite信息:electron-vite官网

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1522838.html

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

相关文章

DDD设计方法-3-仓储,封装持久化数据

前情提要&#xff1a;一共包含 如下六篇文章&#xff08;篇幅精简&#xff0c;快速入门&#xff09; 1、初识DDD 2、聚合、实体、值对象 3、仓储&#xff0c;封装持久化数据 4、端口和适配器 5、领域事件 6、领域服务&#xff0c;实现约定 DDD设计方法-3-仓储&#xff0c;封装…

绿联充电宝怎么样?深度测评西圣、绿联、倍思磁吸充电宝!

在如今这个电子设备不离手的时代&#xff0c;充电宝成为了我们生活中不可或缺的伙伴。而磁吸充电宝以其便捷的使用方式和时尚的外观&#xff0c;更是受到了众多消费者的青睐&#xff0c;今天&#xff0c;我们将对西圣、绿联、倍思这三个品牌的磁吸充电宝进行深度测评&#xff0…

Three之材质Material

本文目录 前言一、基础材质1.1 特点及属性1.2 代码1.3 效果 二、标准材质2.1 特点及属性2.2 代码及效果 三、深度材质四、法向材质五、朗伯材质六、Phong式材质七、粒子材质八、 着色器材质九、其他材质 前言 Three.js中的材质&#xff08;Material&#xff09;是独立于物体顶点…

Anthropic Claude Artifacts,克劳德聊天机器人如何简化代码编程

最近有一位8岁的小男孩&#xff0c;没有任何编程经验&#xff0c;却成功创建了一个网页游戏。他利用了Claude AI和Cursor来生成代码&#xff0c;这充分展示了人工智能在简化编程和创作过程中的巨大潜力。前几天还能看见一个8岁的女孩用生成式人工智能Cursor ai工具可以搭建出一…

一款基于Vue的低代码可视化表单设计器工具,6K star的可视化表单设计器工具,轻松搞定表单,支持多端适配(附源码)

前言 随着Web应用的日益复杂化&#xff0c;表单的设计与开发成为了许多项目中不可或缺的一环。然而&#xff0c;在实际cao作过程中&#xff0c;表单设计往往面临着重复工作量大、效率低下等问题。那么&#xff0c;是否有一款工具能够简化这一过程&#xff0c;提高开发者的效率…

【MySQL07】【锁】

文章目录 一、前言二、事务的读写情况1. 写-写情况2. 读-写情况3. 一致性读4. 锁定读2.1 共享锁和独占锁2.2 锁定读的语句 5. 写操作 三、多粒度锁四、表锁和行锁1. 表级锁1.1 表级别的 S锁 和 X锁1.2 表级别的 IS 锁和 IX锁1.3 表级别的 AUTO-INC 锁 2. 行级锁2.1 行级锁的分类…

【流式输出】LangChain流式输出的概念

&#x1f601; 作者简介&#xff1a;一名大四的学生&#xff0c;致力学习前端开发技术 ⭐️个人主页&#xff1a;夜宵饽饽的主页 ❔ 系列专栏&#xff1a;JavaScript小贴士 &#x1f450;学习格言&#xff1a;成功不是终点&#xff0c;失败也并非末日&#xff0c;最重要的是继续…

记一次头疼事故:springSecurity无法重定向到登录页/springSecurity整合layui后,会话丢失,点击选项卡无法定位到登录页。

1、问题概述? 1、springboot工程引入了springSecurity权限框架实现用户登录功能,当刷新浏览器地址栏的时候能够自动的重定向到登录页实现登录。 2、但是项目中使用了layui的选项卡,当会话丢失的时候(或者重启工程后直接访问),选项卡无法回到登录页,而是选项卡中的数据表…

yolo数据集钢材表面缺陷v8下载适用yolov5等全版本已标注txt格式

钢材表面缺陷检测数据集介绍 数据集概述 本数据集专为钢材表面缺陷检测任务而设计&#xff0c;包含了大量的钢材表面图像&#xff0c;每张图像均带有详细的缺陷标注信息。数据集旨在帮助研究人员和开发人员训练高精度的目标检测模型&#xff0c;以应用于钢材制造和质量控制等多…

建网站公司策划书

建网站公司策划书&#xff1a;建设创新型网站服务企业 一、背景介绍 随着信息时代的来临&#xff0c;互联网已经成为人们生活和工作的重要组成部分。在这个数字化的时代&#xff0c;企业需要强大的在线存在来吸引客户、展示产品和提供服务。为满足市场需求&#xff0c;我们公…

图形语言传输格式glTF和三维瓦片数据3Dtiles(b3dm、pnts)学习

文章目录 3DTilesb3dm一、glTF1.glTF 3D模型格式有两种2.glTF 场景描述结构3.glTF的JSON结构 二、 3DTiles 原文 工具资料 格式详解 格式详解&#xff01; 3D Tiles 是一种开源的、优化的文件格式&#xff0c;支持逐级细节&#xff08;LOD&#xff09;和空间索引&#xff0c;使…

JMeter 快速入门体验,小白也能看得懂!

最近在推进信创转 arm, 遇到的问题是有几个服务在 x86 架构下运行良好&#xff0c;但是在 arm 机器上总是出现问题&#xff0c;为了验证问题&#xff0c;准备使用压测工具做一下压力测试&#xff0c;JMeter 免费开源又好用&#xff0c;趁此机会学习实践一下吧。 JMeter 是开源…

高德地图-小米14 Pro 定制版 v12.10.61.3021 简洁版

高德地图小米14 Pro 定制版是一款专门为小米14 Pro 设计的简洁版高德地图。相较于普通版本&#xff0c;该版本体积更小&#xff0c;运行速度更快&#xff0c;并且没有广告。支持驾车、骑行、公交地铁、步行等多种导航模式&#xff0c;使用北斗卫星导航系统&#xff0c;精准度非…

【机器人学】7-4.六自由度机器人自干涉检测-两圆柱体空间关系【附MATLAB代码】

目录 前言 公式推导 MATLAB代码 前言 前面介绍了两个圆柱的旋转变换&#xff0c;已将两个圆柱体旋转到了比较好分析的位置&#xff0c;下面将正式分析两个圆柱体的位置关系。会借用投影的思想。 一 根据机械臂的几何数据以及DH参数&#xff0c;确定机械臂等…

硬件产品经理进阶:产品层次划分的3个方法

目录 1、内容简介 2、产品三层次概念 3、产品四层次概念 4、产品五层次概念 作者简介 1、内容简介 产品本身指的是能够满足需求和欲望的一种媒介物。 可以是实体、也可以是虚拟的服务。 在产品竞争白热化的今天&#xff0c; 如果只是考虑把产品做出来、 仅仅在实际产…

保存json时,保存成自己喜欢的格式的方法(而不是直接保存成格式化的json文档)

保存json时&#xff0c;不是直接保存成格式化的json文档的格式的方法 前言&#xff0c;博主是如何把格式话的json格式保存成自己喜欢的json格式的保存成格式化的json文档的格式&#xff1a;带缩进格式全部保存成一行每条数据保存成一行&#xff1a; 保存成自己喜欢的格式碎碎念…

红黑树的插入 C++

红黑树与二叉搜索树类似 它在每个节点增加了一个存储位记录节点的颜色&#xff0c;可以是RED,也可以是BLACK&#xff1b;通过任意一条从根到叶子简单路径上颜色的约束&#xff0c;红黑树保证最长路径不超过最短路径的二倍&#xff0c;因而近似平衡&#xff08;最短路径就是全黑…

深入浅出Stream流

Java 8的新特性之一就是流stream&#xff0c;配合同版本出现的 Lambda &#xff0c;使得操作集合&#xff08;Collection&#xff09;提供了极大的便利。 案例引入 在JAVA中&#xff0c;涉及到对数组、Collection等集合类中的元素进行操作的时候&#xff0c;通常会通过循环的…

学习bat脚本

内容包含一些简单命令或小游戏&#xff0c;在乐趣中学习知识。 使用方法&#xff1a; 新建文本文档&#xff0c;将任选其一代码保存到文档中并保存为ASCII编码。将文件后缀改为.bat或.cmd双击运行即可。 一. 关机脚本 1. 直接关机 echo off shutdown -s -t 00秒直接关机。 2…

亿图图示下载安装教程EdrawMax Pro 13版超详细图文教程

亿图图示下载安装教程EdrawMax Pro 13版超详细图文教程&#xff1a; 亿图图示是一款功能强大的综合绘图软件&#xff0c;具有以下特点和功能 丰富的绘图类型&#xff1a;涵盖 210 余种办公绘图类型&#xff0c;包括流程图、思维导图、信息图、工业设计、组织架构图、平面设计…