Electron一小时快速上手

news2025/4/6 1:56:35

1. 什么是 Electron?

Electron 是一个跨平台桌面应用开发框架,开发者可以使用 HTML、CSS、JavaScript 等 Web 技术来构建桌面应用程序。它的本质是结合了 Chromium 和 Node.js,现在广泛用于桌面应用程序开发。例如,以下桌面应用都使用了 Electron 技术:

  • Visual Studio Code
  • GitHub Desktop
  • 1Password
  • 新版 QQ

2. Electron 的优势

  1. 可跨平台:同一套代码可以构建出能在 Windows、macOS、Linux 上运行的应用程序。
  2. 上手容易:使用 Web 技术就可以轻松完成开发桌面应用程序。
  3. 底层权限:允许应用程序访问文件系统、操作系统等底层功能,从而实现复杂的系统交互。
  4. 社区支持:拥有一个庞大且活跃的社区,开发者可以轻松找到文档、教程和开源库。

3. Electron 技术架构

3.1. 技术架构

Electron = Chromium + Node.js + Native API

3.2. 进程模型

---

4. 搭建一个工程

  • 初始化一个包,并填写好 package.json 中的必要信息及启动命令。
{
    "name": "test",
    "version": "1.0.0",
    "main": "main.js",
    "scripts": {
        "start": "electron ." // start命令用于启动整个应用
    },
    "author": "tianyu", // 为后续能顺利打包,此处要写明作者。
    "license": "ISC",
    "description": "this is a electron demo", // 为后续能顺利打包,此处要编写描述。
}
  • 安装 electron 作为开发依赖。
npm i electron -D
  • main.js 中编写代码,创建一个基本窗口。
/*
 main.js运⾏在应⽤的主进程上,⽆法访问Web相关API,主要负责:控制⽣命周期、显示界⾯、
控制渲染进程等其他操作。
*/
const { app, BrowserWindow } = require('electron')

// 用于创建窗口
function createWindow() {
    const win = new BrowserWindow({
        width: 800, // 窗口宽度
        height: 600, // 窗口高度
        autoHideMenuBar: true, // 自动隐藏菜单栏
        alwaysOnTop: true, // 置顶
        x: 0, // 窗口位置x坐标
        y: 0 // 窗口位置y坐标
    })
    // 加载一个远程页面
    win.loadURL('http://www.atguigu.com')
}

// 当app准备好后,执行createWindow创建窗口
app.on('ready', () => {
    createWindow()
})

关于 BrowserWindow 的更多配置项,请参考:BrowserWindow实例属性

  • 启动应用查看效果。
npm start

5. 加载本地页面

  • 创建 pages/index.html 编写内容:
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8" />
    <title>index</title>
</head>
<body>
    <h1>你好啊!</h1>
</body>
</html>
  • 修改 main.js 加载本地页面。
// 加载一个本地页面
win.loadFile('../pages/index.html')
  • 此时开发者工具会报出一个安全警告,需要修改 index.html,配置 CSP (Content Security Policy)。
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:;">
  • 上述配置的说明
  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 的详细说明请参考:MDN – Content Security Policy、Electron Security。

6. 完善窗口行为

  1. Windows 和 Linux 平台窗口特点:关闭所有窗口时退出应用。
// 当所有窗口都关闭时
app.on('window-all-closed', () => {
    // 如果所处平台不是mac(darwin),则退出应用。
    if (process.platform !== 'darwin') app.quit()
})
  1. mac 应用:即使在没有打开任何窗口的情况下也继续运行,并且在没有窗口可用的情况下激活应用时会打开新的窗口。
// 当app准备好后,执行createWindow创建窗口
app.on('ready', () => {
    createWindow()
    // 当应用被激活时
    app.on('activate', () => {
        // 如果当前应用没有窗口,则创建一个新的窗口
        if (BrowserWindow.getAllWindows().length === 0) createWindow()
    })
})

7. 配置自动重启

  1. 安装 nodemon
npm i nodemon -D
  1. 修改 package.json 命令。
"scripts": {
    "start": "nodemon --exec electron ."
}
  1. 配置 nodemon.json 规则。
{
    "ignore": [
        "node_modules",
        "dist"
    ],
    "restartable": "r",
    "watch": ["*.*"],
    "ext": "html,js,css"
}

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

8. 主进程与渲染进程

在这里插入图片描述
Electron 应用的结构与 Chrome 浏览器的程序架构非常相似,主要控制两类进程:主进程、渲染器进程。

8.1. 主进程

每个 Electron 应用都有一个单一的主进程,作为应用程序的入口点。主进程在 Node.js 环境中运行,具有 require 模块和使用所有 Node.js API 的能力。主进程的核心是使用 BrowserWindow 来创建和管理窗口。

8.2. 渲染进程

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

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


9. Preload 脚本

预加载 (Preload) 脚本是运行在渲染进程中的,但它是在网页内容加载之前执行的。这意味着它具有比普通渲染器代码更高的权限,可以访问 Node.js 的 API,同时又可以与网页内容进行安全的交互。

简单说:它是 Node.js 和 Web API 的桥梁,Preload 脚本可以安全地将部分 Node.js 功能暴露给网页,从而减少安全风险。

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

具体文件结构与编码如下:

  1. 创建预加载脚本 preload.js,内容如下:
const { contextBridge } = require('electron')

// 暴露数据给渲染进程
contextBridge.exposeInMainWorld('myAPI', {
    n: 666,
    version: process.version
})
  1. 在主线程中引入 preload.js
const win = new BrowserWindow({
    webPreferences: {
        preload: path.resolve(__dirname, './preload.js')
    }
})
  1. 在 html 页面中编写对应按钮,并创建专门编写网页脚本的 render.js,随后引入。
<body>
    <h1>你好啊!</h1>
    <button id="btn">在用户的 D 盘创建一个 hello.txt</button>
    <script type="text/javascript" src="./render.js"></script>
</body>
  1. 在渲染进程中使用 version
btn.addEventListener('click', () => {
    console.log(myAPI.version)
    document.body.innerHTML += `<h2>${myAPI.version}</h2>`
})
  1. 整体文件结构如下:
    在这里插入图片描述

10. 进程通信 (IPC)

值得注意的是:

上文中的 preload.js,无法使用全部 Node 的 API,比如:不能使用 Node 中的 fs 模块,但主进程(main.js)是可以的,这时就需要进程通信了。简单说:要让 preload.js 通知 main.js 去调用 fs 模块去干活。

关于 Electron 进程通信,我们要知道:

  • IPC 全称为:InterProcess Communication,即:进程通信。
  • IPC 是 Electron 中最为核心的内容,它是从 UI 调用原生 API 的唯一方法!
  • Electron 中,主要使用 ipcMainipcRenderer 来定义“通道”,进行进程通信。

10.1. 渲染进程到主进程(单向)

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

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

需求:

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

  1. index.html页面中添加相关元素,render.js 中添加对应脚本。
<input id="content" type="text"></br></br>
<button id="btn">在用户的 D 盘创建一个 hello.txt</button>
const btn = document.getElementById('btn')
const content = document.getElementById('content')

btn.addEventListener('click', () => {
    console.log(content.value)
    myAPI.saveFile(content.value)
})
  1. preload.js 中使用 ipcRenderer.send('信道', 参数) 发送消息,与主进程通信。
const { contextBridge, ipcRenderer } = require('electron')

contextBridge.exposeInMainWorld('myAPI', {
    saveFile(str) {
        // 渲染进程给主进程发送一个消息
        ipcRenderer.send('create-file', str)
    }
})
  1. main.js主进程中,在加载页面之前,使用 ipcMain.on('信道', 回调) 配置对应回调函数,接收消息。
// 用于创建窗口
function createWindow() {
    // 主进程注册对应回调
    ipcMain.on('create-file', createFile)
    // 加载一个本地页面
    win.loadFile(path.resolve(__dirname, './pages/index.html'))
}

// 创建文件
function createFile(event, data) {
    fs.writeFileSync('D:/hello.txt', data)
}

10.2. 渲染进程到主进程(双向)

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

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

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

需求:

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

  1. index.html页面中添加相关元素,render.js 中添加对应脚本。
<button id="btn">读取用户 D 盘的 hello.txt</button>
const btn = document.getElementById('btn')
btn.addEventListener('click', async () => {
    let data = await myAPI.readFile()
    document.body.innerHTML += `<h2>${data}</h2>`
})
  1. preload.js 中使用 ipcRenderer.invoke('信道', 参数) 发送消息,与主进程通信。
const { contextBridge, ipcRenderer } = require('electron')

contextBridge.exposeInMainWorld('myAPI', {
    readFile(path) {
        return ipcRenderer.invoke('read-file')
    }
})
  1. main.js主进程中,在加载页面之前,使用 ipcMain.handle('信道', 回调) 接收消息,并配置回调函数。
// 用于创建窗口
function createWindow() {
    // 主进程注册对应回调
    ipcMain.handle('read-file', readFile)
    // 加载一个本地页面
    win.loadFile(path.resolve(__dirname, './pages/index.html'))
}

// 读取文件
function readFile(event, path) {
    return fs.readFileSync(path).toString()
}

10.3. 主进程到渲染进程

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

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

需求:

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

  1. 页面中添加相关元素,render.js 中添加对应脚本。
window.onload = () => {
    myAPI.getMessage('logMessage')
}

function logMessage(event, str) {
    console.log(event, str)
}
  1. preload.js 中使用 ipcRenderer.on('信道', 回调) 接收消息,并配置回调函数。
const { contextBridge, ipcRenderer } = require('electron')

contextBridge.exposeInMainWorld('myAPI', {
    getMessage(callback) {
        return ipcRenderer.on('message', callback)
    }
})
  1. main.js主进程中,在合适的时候,使用 win.webContents.send('信道', 数据) 发送消息。
// 用于创建窗口
function createWindow() {
    // 加载一个本地页面
    win.loadFile(path.resolve(__dirname, '../pages/index.html'))
    // 创建一个定时器
    setTimeout(() => {
        win.webContents.send('message', '你好啊!')
    }, 6000)
}

11. 打包应用

使用 electron-builder 打包应用。

  1. 安装 electron-builder
npm install electron-builder -D
  1. package.json 中进行相关配置。

备注:json ⽂件不⽀持注释,使⽤时请去掉所有注释。

{
    "name": "video-tools", // 应用程序的名称
    "version": "1.0.0", // 应用程序的版本
    "main": "main.js", // 应用程序的入口文件
    "scripts": {
        "start": "electron .", // 使用 `electron .` 命令启动应用程序
        "build": "electron-builder" // 使用 `electron-builder` 打包应用程序,生成安装包
    },
    "build": {
        "appId": "com.atguigu.video", // 应用程序的唯一标识符
        // 打包 windows 平台安装包的具体配置
        "win": {
            "icon": "./logo.ico", // 应用图标
            "target": [
                {
                    "target": "nsis", // 指定使用 NSIS 作为安装程序格式
                    "arch": ["x64"] // 生成 64 位安装包
                }
            ]
        },
        "nsis": {
            "oneClick": false, // 设置为 `false` 使安装程序显示安装向导界面,而不是一键安装
            "perMachine": true, // 允许每台机器安装一次,而不是每个用户都安装
            "allowToChangeInstallationDirectory": true // 允许用户在安装过程中选择安装目录
        }
    },
    "devDependencies": {
        "electron": "^30.0.0", // 开发依赖中的 Electron 版本
        "electron-builder": "^24.13.3" // 开发依赖中的 `electron-builder` 版本
    },
    "author": "tianyu", // 作者信息
    "license": "ISC", // 许可证信息
    "description": "A video processing program based on Electron" // 应用程序的描述
}
  1. 执行打包命令。
npm run build

12. electron-vite

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

  • 一套构建指令,使用 Vite 打包代码,并处理 Electron 的独特环境。
  • 集中配置主进程、渲染器和预加载脚本的 Vite 配置。
  • 为渲染器提供快速模块热替换(HMR)支持。
  • 优化 Electron 主进程资源处理。
  • 使用 V8 字节码保护源代码。

electron-vite 快速、简单且功能强⼤,旨在开箱即⽤。官网地址:https://cn-evite.netlify.app/

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

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

相关文章

算法004——盛最多水的容器

力扣——盛最多水的容器点击即可跳转 当我们选择1号线和8号线时&#xff0c;下标为 1 和 8 形成容器的容积的高度是由 较矮的决定的&#xff0c;即下标为 8 的位置&#xff1b; 而宽度则是 1到8 之间的距离&#xff0c;为 8-17&#xff0c;此时容器的容积为 7 * 7 49。 当我…

Java Web-Filter

Filter 在 Java Web 开发中&#xff0c;Filter&#xff08;过滤器&#xff09;是 Servlet 规范中的一个重要组件&#xff0c;它可以对客户端与服务器之间的请求和响应进行预处理和后处理。以下从多个方面详细介绍 Java Web 中的 Filter&#xff1a; 一、概念和作用 概念&…

DeepSeek-R1训练时采用的GRPO算法数学原理及算法过程浅析

先来简单看下PPO和GRPO的区别&#xff1a; PPO&#xff1a;通过奖励和一个“评判者”模型&#xff08;critic 模型&#xff09;评估每个行为的“好坏”&#xff08;价值&#xff09;&#xff0c;然后小步调整策略&#xff0c;确保改进稳定。 GRPO&#xff1a;通过让模型自己生…

七星棋牌 6 端 200 子游戏全开源修复版源码(乐豆 + 防沉迷 + 比赛场 + 控制)

七星棋牌源码 是一款运营级的棋牌产品&#xff0c;覆盖 湖南、湖北、山西、江苏、贵州 等 6 大省区&#xff0c;支持 安卓、iOS 双端&#xff0c;并且 全开源。这个版本是 修复优化后的二开版本&#xff0c;新增了 乐豆系统、比赛场模式、防沉迷机制、AI 智能控制 等功能&#…

CSDN博客导出设置介绍

在CSDN编辑博客时&#xff0c;如果想导出保存到本地&#xff0c;可以选择导出为Markdown或者HTML格式。其中导出为HTML时有这几种选项&#xff1a;jekyll site&#xff0c;plain html&#xff0c;plain text&#xff0c;styled html&#xff0c;styled html with toc。分别是什…

音视频-WAV格式

1. WAV格式说明&#xff1a; 2. 格式说明&#xff1a; chunkId&#xff1a;通常是 “RIFF” 四个字节&#xff0c;用于标识文件类型。&#xff08;wav文件格式表示&#xff09;chunkSize&#xff1a;表示整个文件除了chunkId和chunkSize这 8 个字节外的其余部分的大小。Forma…

apload-lab打靶场

1.提示显示所以关闭js 上传<?php phpinfo(); ?>的png形式 抓包&#xff0c;将png改为php 然后放包上传成功 2.提示说检查数据类型 抓包 将数据类型改成 image/jpeg 上传成功 3.提示 可以用phtml&#xff0c;php5&#xff0c;php3 4.先上传.htaccess文件&#xff0…

sentinel详细使用教学

sentinel源码地址&#xff1a; https://github.com/alibaba/Sentinel/wiki/%E4%BB%8B%E7%BB%8D sentinel官方文档&#xff1a; https://sentinelguard.io/zh-cn/docs/introduction.html Sprong Cloud alibaba Sentinel文档【小例子】 : https://github.com/alibaba/spring-cl…

python django

官网地址 https://www.djangoproject.com/ 安装 控制台输入命令 pip install django 或者可以指定版本号 pip install django3.2.4 创建项目 在控制台找个目录存放生成好的项目&#xff0c;输入命令 django-admin startproject demo_django 然后用pycharm打开项目可以…

SuperMap iClient3D for WebGL 影像数据可视范围控制

在共享同一影像底图的服务场景中&#xff0c;如何基于用户权限体系实现差异化的数据可视范围控制&#xff1f;SuperMap iClient3D for WebGL提供了自定义区域影像裁剪的方法。让我们一起看看吧&#xff01; 一、数据制作 对于上述视频中的地图制作&#xff0c;此处不做讲述&am…

OpenHarmony4.1-轻量与小型系统ubuntu开发环境

因OpenHarmony官网提供包含轻量、小型与标准系统的全量代码非常宠大&#xff0c;解包后大概需要70G以上硬盘空间&#xff0c;如要编译标准系统则需要140G以上空间。 如硬盘空间有限与只使用轻量/小型OpenHarmony系统&#xff0c;则可以下载并直接使用本人裁剪源码过的ubuntu硬盘…

秒杀系统的常用架构是什么?怎么设计?

架构 秒杀系统需要单独部署&#xff0c;如果说放在订单服务里面&#xff0c;秒杀的系统压力太大了就会影响正常的用户下单。 常用架构&#xff1a; Redis 数据倾斜问题 第一步扣减库存时 假设现在有 10 个商品需要秒杀&#xff0c;正常情况下&#xff0c;这 10 个商品应该均…

LabVIEW中三种PSD分析VI的区别与应用

在LabVIEW的声音与振动分析工具包中&#xff0c;SVFA Power Spectral Density VI、SVFA Power Spectral Density Subset VI 和 SVFA Zoom Power Spectral Density VI 均用于信号频域分析&#xff0c;但它们在功能、适用场景和操作逻辑上存在显著差异。以下从区别、应用场合、注…

蓝桥杯备考:动态规划入门题目之下楼梯问题

按照动态规划解题顺序&#xff0c;首先&#xff0c;我们要定义状态表示&#xff0c;这里根据题意f[i]就应该表示有i个台阶方案总数 第二步就是 确认状态转移方程&#xff0c;画图分析 所以实际上f[i] 也就是说i个台阶的方案数实际上就是第i-1个格子的方案数第i-2个格子的方案数…

【树莓派学习】树莓派3B+的安装和环境配置

【树莓派学习】树莓派3B的安装和环境配置 文章目录 【树莓派学习】树莓派3B的安装和环境配置一、搭建Raspberry Pi树莓派运行环境1、下载树莓派镜像下载器2、配置wifi及ssh3、SSH访问树莓派1&#xff09;命令行登录2&#xff09;远程桌面登录3&#xff09;VNC登录&#xff08;推…

算法题(83):寄包柜

审题&#xff1a; 需要我们对模拟柜子的数组进行插入数据和打印数据的操作 思路&#xff1a; 首先我们观察题目&#xff0c;发现可以用一个数组表示一个柜子&#xff0c;而数组中每个索引的位置可以看成是一个个格子。但是柜子的数据量是1e5&#xff0c;且格子的数据量是1e5.如…

深入浅出MySQL:概述与体系结构解析

目录 1. 初识MySQL 1.1. 数据库 1.1.1. OLTP&#xff08;联机事务处理&#xff09;1.1.2. OLAP&#xff08;联机分析处理&#xff09; 2. SQL 2.1. 定义2.2. DQL&#xff08;数据查询语言&#xff09;2.3. DML&#xff08;数据操纵语言&#xff09;2.4. DDL&#xff08;数据定…

tin这个单词怎么记

英语单词 tin&#xff0c;一般用作名词&#xff0c;意为“罐头&#xff1b;锡”&#xff1a; tin n.锡&#xff1b;罐头&#xff1b;罐&#xff1b;罐头盒&#xff1b;(盛涂料、胶水等的)马口铁罐&#xff0c;白铁桶&#xff1b;罐装物&#xff1b;金属食品盒&#xff1b;烘焙…

【0005】Python变量详解

如果你觉得我的文章写的不错&#xff0c;请关注我哟&#xff0c;请点赞、评论&#xff0c;收藏此文章&#xff0c;谢谢&#xff01; 本文内容体系结构如下&#xff1a; 任何一个语言编写的程序或者项目&#xff0c;都需要数据的支持&#xff0c;没有数据的项目不能称之为一个…

yolov8_pose模型,使用rknn在安卓RK3568上使用

最近在使用rknn的一些功能,看了看文档以及自己做的一些jni,使用上yolov8_pose的模型. 1.我们先下载一下rknn的模型功能代码,rk有自己做的一套demo 地址:GitHub - airockchip/rknn_model_zooContribute to airockchip/rknn_model_zoo development by creating an account on G…