electron快速上手

发布于:2024-11-23 ⋅ 阅读:(16) ⋅ 点赞:(0)

1、electron

  • 一款应用广泛的跨平台的桌面应用开发框架
  • electron本质是结合了chromium与node.js
    在这里插入图片描述
  • 使用html、css、js等web技术构建桌面应用程序(vue tsx less ts)

2、 electron流程模型

在这里插入图片描述

main 可以__dirname fs
render进程可以 alert() window()

3、创建

1、新建一个文件夹
2、执行

npm init

3、对package.json修改
必须设置author和description 否则不能打包
“main”: “main.js”

{
	"name": "electron-test",
	"version": "1.0.0",
	"description": "Hello World",
	"main": "main.js",
	"scripts": {
		"start": "electron ."
	},
	"author": "liweina",
	"license": "ISC",
	"devDependencies": {
		"electron": "^33.2.0"
	}
}

4、安装electron依赖

npm i electron -D

5、创建一个文件main.js
main.js 创建一个窗口

// app相当于桌面应用 ,地基  BrowserWindow浏览器窗口 所有窗口都需要它new出来
const { app, BrowserWindow } = require('electron')
// 当应用准备好时会调用
app.on('ready', () => {
	// 创建一个窗口
	let win = new BrowserWindow({
		width: 800,
		height: 600,
		autoHideMenuBar: true, //自动隐藏菜单栏
		x: 0,
		y: 0, //窗口的位置 在左上角
		alwaysOnTop: true //窗口一直置顶
	})
	win.loadURL('https://www.baidu.com')
})

更多BrowserWindow的配置项请点此处
6、运行 npm start

4、加载一个本地页面

  • main.js修改
//将url加载换成这个就行
	win.loadFile('./pages/index.html') //加载一个文件
  • 在index.html编写代码
<!DOCTYPE html>
 <html>
 <head>
 <meta charset="UTF-8" />
 <title>index</title>
 </head>
 <body>
 <h1>
你好啊!
</h1>
 </body>
  • 此时开发者⼯具会报出⼀个安全警告,需要修改index.html ,配置 CSP(Content-Security-Policy)
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; st
yle-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 的详细说明请参考:
Content-Security-Policy
electron-security

5、打开控制台 ctrl+shift+i

在窗口打开控制台 ctrl+shift+i

6、完善窗口行为

windows和Linux:应用所有的窗口都关闭,那么应用自动退出

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

macos: 应用退出了,但其实在Dock栏里还能看出
mac应用即使在没有打开窗口的情况下也继续运行,并且在没有窗口可用的情况下激活应用时会打开新的窗口

// 当应用准备好时会调用
app.on('ready', () => {
	createWindow()
	// 当窗口被激活的时候, 这是给苹果电脑看的
	app.on('activate', () => {
		// 当前窗口数量是0,就创建一个窗口
		if (BrowserWindow.getAllWindows().length === 0) createWindow()
	})
})

7、配置自动重启

1、安装nodemon

npm i nodemon -D

更改package.json

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

配置nodemon.json规则

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

main.js是运行在主进程
如果main.js打印控制台中文乱码,更改package.json

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

8、主进程与渲染进程

主进程 main.js

// app相当于桌面应用 ,地基  BrowserWindow浏览器窗口 所有窗口都需要它new出来
const { app, BrowserWindow } = require('electron')
const path = require('path')
function createWindow() {
	// 创建一个窗口
	let win = new BrowserWindow({
		width: 800,
		height: 600,
		autoHideMenuBar: true, //自动隐藏菜单栏
		webPreferences: {
			preload: path.resolve(__dirname, './preload.js') //写绝对路径)
		},
		x: 0,
		y: 0, //窗口的位置 在左上角
		alwaysOnTop: true //窗口一直置顶
	})
	// win.loadURL('https://www.baidu.com')    //加载一个url
	win.loadFile('./pages/index.html') //加载一个文件
}
console.log(process.version)
console.log(process.versions.chrome)
// 当应用准备好时会调用
app.on('ready', () => {
	console.log('应用准备好了easy1111')
	createWindow()
	// 当窗口被激活的时候, 这是给苹果电脑看的
	app.on('activate', () => {
		// 当前窗口数量是0,就创建一个窗口
		if (BrowserWindow.getAllWindows().length === 0) createWindow()
	})
})
// 当所有的窗口都关闭时
app.on('window-all-closed', () => {
	// 不是苹果系统  退出
	if (process.platform !== 'darwin') app.quit()
})

渲染进程 和html并列的render.js

const btn1 = document.querySelector('#btn1')
btn1.onclick = () => {
	alert('点我了')
	console.log(versions.version)
}
console.log('render')
console.log(window)
console.log(versions.version)

9、preload脚本

预加载脚本 运行在渲染进程上 能执行一部分的node api 通过它联系主进程和渲染进程 主进程和渲染进程的桥梁

// 预加载脚本 运行在渲染进程上 能执行一部分的node api 通过它联系主进程和渲染进程
console.log('preload', process.version)
// 在主进程和渲染进程之间安全地创建一个受限的通信桥梁
const { contextBridge } = require('electron')
// 主世界曝光  暴露给渲染进程
contextBridge.exposeInMainWorld('versions', {
	version: process.version,
	node: process.versions.node
})

10、进程通信

值得注意的是:
上文中的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文件,文件内容;来源与用户输入

index.html

	<input id="input" type="text" />
		<button id="btn2">向D盘写入hello.txt</button>

render.js

const input = document.querySelector('#input')
const btn2 = document.querySelector('#btn2')
btn2.onclick = () => {
	myAPI.saveFile(input.value)
}

preload.js

const input = document.querySelector('#input')
const btn2 = document.querySelector('#btn2')
btn2.onclick = () => {
	myAPI.saveFile(input.value)
}

main.js

const { app, BrowserWindow, ipcMain } = require('electron')
// 调用node的fs模块  和文件系统交互,操作文件和目录
const fs = require('fs')
//写入文件
function writeFile(_, data) {
	// 同步写入文件 会堵塞进程
	fs.writeFileSync('D:/hello.txt', data)
}
function createWindow() {
	/********/
	//主进程注册对应回调
	ipcMain.on('file-save', writeFile)
	win.loadFile('./pages/index.html') //加载一个文件
}

10.2 渲染进程<—>主进程 双向

概述:渲染进程通过ipcRenderer.invokie发送消息,主进程使用ipcMain.handle接收并处理消息
适合需要主进程处理并返回结果的交互场景
备注:ipcRender.invoke的返回值是Promise实例。
常用于:从渲染器进程调用主线程方法并等待结果

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

index.html

		<button id="btn3">读取D盘的hello.txt</button>

render.js

const btn3 = document.querySelector('#btn3')
btn3.onclick = async () => {
	let data = await myAPI.readFile()
	alert(data)
}

preload.js

contextBridge.exposeInMainWorld('myAPI', {
	version: process.version,
	node: process.versions.node,
	saveFile: data => {
		ipcRenderer.send('file-save', data)
	},
	readFile() {
		return ipcRenderer.invoke('file-read')
	}
	// async readFile() {
	// 	// invoke有调用的意思  invoke返回值是promise
	// 	let x = await ipcRenderer.invoke('file-read')
	// 	console.log(x)
	// }
})

main.js

const { app, BrowserWindow, ipcMain } = require('electron')
// 调用node的fs模块  和文件系统交互,操作文件和目录
const fs = require('fs')
function readFile() {
	// 读出来东西是buffer
	return fs.readFileSync('D:/hello.txt').toString()
}
function createWindow() {
	/*******/
	ipcMain.handle('file-read', readFile)
	win.loadFile('./pages/index.html') //加载一个文件
}

10.3 主进程->渲染进程

render.js

//当页面的所有内容都已经完全加载并初始化完成后就会执行此函数
window.onload = () => {
	myAPI.mainSend(getMainSendCallback)
}
function getMainSendCallback(event,data) {
	console.log(11111)
	console.log(event, data)
}

preload.js

contextBridge.exposeInMainWorld('myAPI', {
	version: process.version,
	node: process.versions.node,
	mainSend: callback => {
		return ipcRenderer.on('main-send', callback)
	}
})

main.js

const { app, BrowserWindow, ipcMain } = require('electron')
function createWindow() {
	/**********/
	win.loadFile('./pages/index.html') //加载一个文件
	//必须加载完后才能发送消息
	setTimeout(() => {
		win.webContents.send('main-send', 11111)
	}, 600)
}

11.打包应用

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

npm install electron-builder -D

2、在package.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"  // 应⽤程序的描述
}

12.electron-vite

实际开发可以用这个框架 更便捷和好使用

electron-vite官网