Electron
Electron是由GitHub开发的一个开源框架,允许开发者使用JavaScript、HTML和CSS来构建跨平台桌面应用程序。
它嵌入了Chromium和Node.js到二进制的Electron中,这使得开发者能在Windows、macOS和Linux上运行他们的代码,而不需要具备特定的本地开发经验。
Electron的原理在于将Chromium定制并集成在内部,使得我们可以调用丰富的原生API来创建桌面应用。因此,开发者可以在Electron中使用所有HTML5、CSS3、ES6标准中定义的API。
理论上,基于Electron开发的应用程序也可以迁移到Web端,甚至套壳为Android和iOS应用,但是否适合需要根据具体产品需求来判断。
Electron = Chromium + Node.js + Native API
- Chromium:为Electron提供了强大的UI能力,可以不考虑兼容性的情况下,利用强大的Web生态来开发界面
- Node.js:让Electron有了底层的操作能力,比如文件的读写,甚至是集成C++等等操作,并可以使用大量开源的npm包来完成开发需求
- Native API:Native API让Electron有了跨平台和桌面端的原生能力,比如说它有统一的原生界面,窗口、托盘这些
在Windows操作系统上,使用Electron需要完成以下步骤:
- 首先,您需要安装Node.js和npm。这两个工具是开发Electron应用程序的基础环境。
- 接下来,您需要在命令行中执行相关命令来安装Electron的开发版本。
- 创建一个新的JavaScript文件,例如app.js,并编写主进程代码。主进程是应用程序的入口点,负责创建窗口。
- 同样地,您需要创建另一个JavaScript文件,例如index.js,并在这里编写渲染进程代码。渲染进程是应用程序的GUI部分,负责显示窗口内容。
- 接下来,您需要在package.json文件中配置main字段,指向app.js文件。
- 最后一步是使用命令行运行
electron .
命令启动应用程序。
此外,如果您希望将您的应用程序打包成一个可在多个操作系统上运行的可执行文件,可以使用electron-builder。electron-builder是一个用于构建跨平台桌面应用程序的Electron插件,它支持Windows、macOS、Linux等操作系统,并且还可以生成适用于Android和iOS的移动应用程序。
安装Node.js 和 NPM
Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行时环境,它允许在服务器端运行 JavaScript 代码。
npm(Node Package Manager)是 Node.js 的包管理器,用于安装和管理第三方库和模块。
NPM与Node.js的发展是紧密相连的。Node.js最初由在德国工作的美国程序员Ryan Dahl编写。由于Node.js缺少一个包管理器,Ryan Dahl便决定创建npm,并将其内置在了Node.js中。
在学习Node.js时,建议首先明确自己的学习目标,然后聚焦于关键技能【二八定律】的学习。此外,对于已经掌握前端技术的开发人员来说,无需花费大量精力去学习JavaScript,因为Node.js基于JavaScript,许多概念是相通的。
NVM,全称Node Version Manager,是一个命令行应用,它的主要功能是协助用户快速地更新、安装、使用和卸载本机的全局node.js版本。有时候,我们可能会同时进行多个项目的开发,而这些项目可能使用的是不同版本的node.js,或者需要用到最新的node.js版本进行开发。
NVM的使用场景并不仅限于node.js的版本管理,它还允许用户在同一台机器上创建和管理多个node.js环境。这对于执行需要不同node.js版本的任务非常有用,比如在开发过程中需要用到不同版本的node.js。
如果你的开发需求中需要用到不同版本的node.js,或者需要频繁切换不同的node.js版本,那么NVM将是一个非常有用的工具。
然而,如果你的开发项目中并不需要使用不同版本的node.js,或者你愿意通过搜索Node.js官网来手动下载和安装你需要的node.js版本,那么就没有必要非得使用NVM。此外,请注意,NVM是源shell函数,不是可执行文件,因此我们不能直接运行nvm命令,而应该通过. nvm/nvm.sh
或source nvm/nvm.sh
等命令来调用它。
NPX,全称Node Package Executor,是随同npm5.2.0版本一起引入的一个工具包。它主要被定义为npm包的执行者,不过与npm不同的是,npx在执行的时候会自动安装依赖包。
具体来说,NPX主要用于命令行的寻址等辅助功能。比如你想运行一个项目里的命令行程序,你只需要在终端输入npx [command]
就可以直接运行了。而这个过程中,如果本地没有安装对应的可执行文件,npx还会帮你自动安装所需的依赖。这无疑大大提高了开发者的工作效率。
推荐安装指南:Windows下安装nvm、npm及node.js
- 此指南是以nvm的方式来安装 node.js 和 npm
- node.js版本按需求下载【可查看官网最新版本Node.js】,不一定非要和教程一致
- 安装node.js的过程中,对应的npm也会安装
- nvm --管理--> node.js和npm
- npm/cnpm(国内) --辅助--> node.js
安装Electron
参照:安装使用electron辛路历程 - 小嘉欣 - 博客园
踩坑总结:
cmd
npm install electron -g
大概率命令执行失败,原因是npm
速度超慢,建议把 npm
的仓库切换到国内淘宝仓库,注册 cnpm
命令
cmd
npm install -g cnpm --registry==https://registry.npm.taobao.org
cnpm install electron -g
检测是否安装成功
cmd
electron -v
安装打包输出工具
cmd
npm install -g electron-packager
如何进行Electron应用开发
官方文档:Electron 中文网
可从electron-quick-start作为切入点入手:
- Git克隆到本地仓库:github.com/electron/el...
- 如何运行ElectronApp:
electron .
<==>electron .\项目路径
<==>electron.exe 项目路径
- 基于electron的二次开发
bash
# Clone this repository
git clone https://github.com/electron/electron-quick-start
# Go into the repository
cd electron-quick-start
# Install dependencies
npm install
# Run the app
npm start
# 在此基础上可以进行二次开发
- 怎么将应用打包
.exe
- Electron-builder github.com/electron-us...
- electron-packager github.com/electron/pa...
electron-quick-start
这部分内容是对第一个 Electron App - electron-quick-start 进行分析,从而更好地进行二次开发。
一个基本的Electron应用程序只需要这些文件:
package.json
- 指向应用程序的主文件并列出其详细信息和依赖项;main.js
- 启动应用程序并创建浏览器窗口以呈现HTML;这是app的主要功能;index.html
- 要渲染的网页;这是应用程序的渲染过程;preload.js
- 在渲染器进程加载之前运行的内容脚本;
main.js
js
// Modules to control application life and create native browser window
const { app, BrowserWindow } = require('electron')
const path = require('node:path')
function createWindow () {
// Create the browser window.
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, 'preload.js')
}
})
// and load the index.html of the app.
mainWindow.loadFile('index.html')
// Open the DevTools.
// mainWindow.webContents.openDevTools()
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(() => {
createWindow()
app.on('activate', function () {
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on('window-all-closed', function () {
if (process.platform !== 'darwin') app.quit()
})
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.
第一个部分:导入框架模块,定义所需变量
js
// Modules to control application life and create native browser window
const { app, BrowserWindow } = require('electron')
const path = require('node:path')
- 导入Electron框架中的两个核心模块
- app 模块用于控制应用程序的生命周期
- BrowserWindow 模块用于创建浏览器窗口
- Node.js 内置的
path
模块,它提供了处理文件和目录路径的功能
require
是一个在 Node.js 和 Electron 框架中常用的关键字,用于加载其他模块或依赖项。它遵循 CommonJS 规范,该规范的核心是通过 require
来加载其他模块。此外,require
是同步加载模块文件内容,编译执行后得到模块接口。
然而,需要注意的是,虽然在 Node.js 环境中可以使用 require
关键字导入 CommonJS 模块,但在浏览器环境中,require
是不被支持的。取而代之的是,在 ES6 模块规范中,我们使用 import
关键字来导入模块。
这段代码的目的是创建一个基本的 Electron 应用程序窗口。 通过导入所需的模块并定义一个常量来引用它们,可以方便地在后续的代码中使用这些模块。
第二个部分:定义窗口
js
function createWindow () {
// Create the browser window.
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, 'preload.js')
}
})
// and load the index.html of the app.
mainWindow.loadFile('index.html')
// Open the DevTools.
// mainWindow.webContents.openDevTools()
}
function createWindow () { ... }
:定义一个名为createWindow
的函数,该函数没有参数const mainWindow = new BrowserWindow({ ... })
:创建了一个新的BrowserWindow
对象,并将其赋值给常量mainWindow
。这个新窗口的宽度为 800 像素,高度为 600 像素webPreferences: { preload: path.join(__dirname, 'preload.js') }
:一个配置对象,用于设置新窗口的一些属性。在这个例子中,它设置了预加载脚本的路径,预加载脚本位于当前目录下的preload.js
文件mainWindow.loadFile('index.html')
:将新窗口加载index.html
文件mainWindow.webContents.openDevTools()
:如果取消注释这一行,那么新窗口将会打开开发者工具
这段代码的作用是创建一个新的浏览器窗口,并加载 index.html
文件。同时,它还允许开发者在需要时打开开发者工具。
第三部分:打开窗口
js
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(() => {
createWindow()
app.on('activate', function () {
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
app.whenReady().then(() => { createWindow() })
: 当Electron完成初始化并准备好创建浏览器窗口时,会调用app.whenReady()
方法。这个方法返回一个Promise对象,当这个Promise对象被解析(即Electron准备好)时,就会执行then()
方法中的回调函数,也就是createWindow()
方法。app.on('activate', function () {...})
: 这是一个事件监听器,它会在应用程序被激活时触发。在这个事件中,我们检查当前是否有打开的浏览器窗口,如果没有,就调用createWindow()
方法创建一个新的窗口。if (BrowserWindow.getAllWindows().length === 0) createWindow()
: 这是条件判断语句,它检查当前是否有打开的浏览器窗口。BrowserWindow.getAllWindows()
方法返回一个包含所有打开的浏览器窗口的数组,然后我们检查这个数组的长度是否为0,如果为0,说明没有打开的窗口,我们就调用createWindow()
方法创建一个新的窗口。
-
app.on('activate', function () {...})
: 事件监听器的定义app.on()
方法用于监听应用程序的事件- 第一个参数是要监听的事件名称
- 第二个参数是要在事件发生时执行的回调函数
-
if (BrowserWindow.getAllWindows().length === 0) createWindow()
: 这是条件判断语句BrowserWindow.getAllWindows()
方法返回一个包含所有打开的浏览器窗口的数组,- 然后我们检查这个数组的长度是否为0,
- 如果为0,说明没有打开的窗口,我们就调用
createWindow()
方法创建一个新的窗口
index.html
html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'">
<link href="./styles.css" rel="stylesheet">
<title>Hello World!</title>
</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>.
<!-- You can also require other files to run in this process -->
<script src="./renderer.js"></script>
</body>
</html>
-
<!DOCTYPE html>
:声明文档类型为HTML5 -
<html>
:HTML文档的根元素-
<head>
:包含文档的元数据(如字符集、样式表链接等)<meta charset="UTF-8">
:指定文档的字符编码为UTF-8<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'">
: 设置内容安全策略,限制资源加载的来源和方式<link href="./styles.css" rel="stylesheet">
: 引入外部CSS样式表文件<title>
: 定义文档的标题,显示在浏览器标签页上
-
<body>
:包含文档的主体内容<h1>
: 一级标题
-
preload.js
js
/**
* The preload script runs before. It has access to web APIs
* as well as Electron's renderer process modules and some
* polyfilled Node.js functions.
*
* https://www.electronjs.org/docs/latest/tutorial/sandbox
*/
window.addEventListener('DOMContentLoaded', () => {
const replaceText = (selector, text) => {
const element = document.getElementById(selector)
if (element) element.innerText = text
}
for (const type of ['chrome', 'node', 'electron']) {
replaceText(`${type}-version`, process.versions[type])
}
})
window.addEventListener('DOMContentLoaded', () => {...})
:这行代码监听了浏览器的"DOMContentLoaded"事件。当HTML文档被完全加载和解析完成后,这个事件会被触发。在这个回调函数中,我们可以执行一些操作,比如修改页面内容或者初始化一些功能。const replaceText = (selector, text) => {...}
:这是一个箭头函数,它接受两个参数:一个选择器(用于定位页面元素)和一个文本字符串。这个函数的作用是将指定选择器的元素的内容替换为给定的文本。for (const type of ['chrome', 'node', 'electron']) {...}
:这是一个循环,遍历一个包含三个元素的数组:'chrome'、'node'和'electron'。对于数组中的每个元素,都会执行循环体中的代码。
总的来说,这段代码的作用是在页面加载完成后 ,将页面上的三个元素的内容替换为对应的版本信息。
package.json
json
{
"name": "electron-quick-start",
"version": "1.0.0",
"description": "A minimal Electron application",
"main": "main.js",
"scripts": {
"start": "electron ."
},
"repository": "https://github.com/electron/electron-quick-start",
"keywords": [
"Electron",
"quick",
"start",
"tutorial",
"demo"
],
"author": "GitHub",
"license": "CC0-1.0",
"devDependencies": {
"electron": "^27.0.3"
}
}
这段代码是一个项目的package.json
文件,它定义了项目的一些元数据和依赖关系。
- "name": "electron-quick-start" - 项目的名称是"electron-quick-start"。
- "version": "1.0.0" - 项目的版本号是1.0.0。
- "description": "A minimal Electron application" - 项目的描述是"一个最小的Electron应用程序"。
- "main": "main.js" - 项目的主入口文件是"main.js"。
- "scripts": {"start": "electron ."} - 项目有一个名为"start"的脚本,当你在命令行中运行"npm start"时,它将执行"electron ."命令,启动Electron应用程序。
- "repository": "github.com/electron/el..." - 这是项目的GitHub仓库地址。
- "keywords": ["Electron", "quick", "start", "tutorial", "demo"] - 这些关键字描述了项目的内容和用途。
- "author": "GitHub" - 这个项目的作者是GitHub。
- "license": "CC0-1.0" - 这个项目使用了一个名为"CC0-1.0"的公共领域许可证。
- "devDependencies": {"electron": "^27.0.3"} - 这个对象列出了项目的开发依赖项,这里只有一个依赖项,即Electron框架,版本号为27.0.3。
总的来说,这个package.json
文件定义了一个基本的Electron应用程序的项目结构,包括项目名称、版本、描述、主入口文件、脚本、仓库地址、关键字、作者、许可证以及开发依赖项等信息。
json 文件的作用是什么,项目中不存在此文件会怎么样?
JSON,即JavaScript Object Notation(JavaScript对象表示法),是一种轻量级的数据交换格式。它基于ECMAScript的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得JSON成为理想的数据交换语言。在Web开发中,JSON主要应用于Ajax异步访问数据、RPC远程调用、前后端分离后端返回的数据以及开放API等场景。
JSON文件主要应用于前后端交互场景,为数据交互提供了统一的格式。
在项目中,JSON文件的作用主要表现在处理和管理数据方面。例如,Python脚本处理的文本后缀就是.json
;许多软件的配置文件也会使用JSON文件格式。特别的,像package.json这样的文件会包含项目或模块包的描述信息,如项目名称、项目版本、项目执行入口文件、项目贡献者等等,npm install命令会根据这个文件下载所有依赖模块。
至于项目中不存在JSON文件的影响,这取决于具体的项目需求和实现方式。如果项目中并未使用到需要处理JSON格式数据的功能,那么不存在JSON文件并不会产生任何影响。然而,如果存在相关功能需求,如前后台数据交互等,那么缺少必要的JSON文件则可能导致项目无法正常运行。