electron初次学习
一、electron简介
Electron 是一个使用 JavaScript、HTML 和 CSS 构建桌面应用程序的框架,由GitHub众多开发者开发的一个开源项目。嵌入 Chromium 和 Node.js 到 二进制的 Electron 允许保持一个 JavaScript 代码并创建 在Windows上运行的跨平台应用。
二、electron安装
1.在使用Electron进行开发之前,需要安装 Node.js
检查 Node.js 是否正确安装,终端输入以下命令:
node -v
npm -v
因为 Electron 将 Node.js 嵌入到其二进制文件中,你应用运行时的 Node.js 版本与你系统中运行的 Node.js 版本无关。
Electron 应用程序遵循与其他 Node.js 项目相同的结构。
2.创建一个文件夹并初始化 npm 包。
npm init
- entry point 应为 main.js.
- author 与 description 可为任意值,但对于应用打包是必填项。
package.json 文件应该像这样
{
"name": "demo-test",
"version": "1.0.0",
"description": "测试",
"main": "main.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "hdat",
"license": "ISC"
}
3.将 electron 包安装到应用的开发依赖中
npm install --save-dev electron
在 package.json 配置文件中的 scripts 字段下增加一条 start 命令:
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "electron ."
},
start 命令能在开发模式下打开应用
npm start
目前的配置文件为
{
"name": "demo-test",
"version": "1.0.0",
"description": "测试",
"main": "main.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "electron ."
},
"author": "hdat",
"license": "ISC",
"dependencies": {
"electron": "^22.0.0"
}
}
4.配置自动刷新页面
1.安装插件
cnpm install --save-dev electron-reloader
2.在入口引入插件
const reloader = require('electron-reloader');
reloader(module);
5.调试
ctrl+shift+i 打开渲染进程调试
默认打开调试
mainWindow.webContents.openDevTools()
三、electron运行
1.运行主线程
任何 Electron 应用程序的入口都是 main 文件。 这个文件控制了主进程,它运行在一个完整的 Node.js 环境中,负责控制应用的生命周期,显示原生界面,执行特殊操作并管理渲染器进程。
执行期间,Electron 将依据应用中 package.json 配置下 main 字段中配置的值查找此文件
要初始化这个main文件,需要在项目的根目录下创建一个名为main.js的空文件。
2.主进程和渲染进程
Electron 运行 package.json 的 main 脚本的进程被称为主进程。 在主进程中运行的脚本通过创建web页面来展示用户界面。 一个 Electron 应用总是有且只有一个主进程。
由于 Electron 使用了 Chromium 来展示 web 页面,所以 Chromium 的多进程架构也被使用到。 每个 Electron 中的 web 页面运行在它的叫渲染进程的进程中。
在普通的浏览器中,web页面无法访问操作系统的原生资源。 然而 Electron 的用户在 Node.js 的 API 支持下可以在页面中和操作系统进行一些底层交互。
3.在窗口中打开页面
现在有一个 html 页面,将它加载进应用窗口中。 要做到这一点,需要 两个Electron模块:
- app 模块,它控制应用程序的事件生命周期。
- BrowserWindow 模块,它创建和管理应用程序 窗口。
1.因为主进程运行着 Node.js,所以可以在 main.js 文件头部将它们导入作为 CommonJS 模块:
const { app, BrowserWindow } = require('electron')
2.在 Electron 中,只有在 app 模块的 ready 事件被激发后才能创建浏览器窗口。
可以通过使用 app.whenReady() API来监听此事件
app.whenReady().then(() => {
//创建浏览器窗口
})
也可以通过监听的方式
// 监听初始化完成的声明周期
app.on('ready',() => {
//创建浏览器窗口
})
3.创建浏览器窗口并加载页面
// 监听初始化完成的声明周期
app.on('ready',() => {
const mainWindow = new BrowserWindow({
height: 500,
width:500
});
//将 index.html 加载进 BrowserWindow 实例
mainWindow.loadFile('./src/index.html');
// 窗口显示的内容可以是本地HTML文件,也可以是一个远程url
// mainWindow.loadURL('https://www.baidu.com/');
})
现在就可以在窗口中看到页面了
4.管理窗口的生命周期
虽然现在可以打开一个浏览器窗口,但还需要一些额外的模板代码使其看起来更像是各平台原生的。 应用程序窗口在每个OS下有不同的行为,Electron 将在 app 中实现这些约定的责任交给开发者们。
关闭所有窗口时退出应用 (Windows & Linux)
在Windows和Linux上,关闭所有窗口通常会完全退出一个应用程序。
为了实现这一点,你需要监听 app 模块的 ‘window-all-closed’ 事件。如果用户不是在 macOS(darwin) 上运行程序,则调用 app.quit()。
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') app.quit()
})
如果没有窗口打开则打开一个窗口 (macOS)
当 Linux 和 Windows 应用在没有窗口打开时退出了,macOS 应用通常即使在没有打开任何窗口的情况下也继续运行,并且在没有窗口可用的情况下激活应用时会打开新的窗口。
为了实现这一特性,监听 app 模块的 activate 事件。如果没有任何浏览器窗口是打开的,则调用 createWindow() 方法。
因为窗口无法在 ready 事件前创建,你应当在你的应用初始化后仅监听 activate 事件。
app.whenReady().then(() => {
createWindow()
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
目前代码:
const { app,BrowserWindow } = require('electron')
// 热加载
const reloader = require('electron-reloader');
reloader(module);
//创建窗口并加载index.html
const createWindow = () => {
const mainWindow = new BrowserWindow({
height: 500,
width:500
});
//将 index.html 加载进 BrowserWindow 实例
mainWindow.loadFile('./src/index.html');
// 窗口显示的内容可以是本地HTML文件,也可以是一个远程url
// mainWindow.loadURL('https://www.baidu.com/');
};
// 监听初始化完成的声明周期
app.on('ready',() => {
createWindow();
// 在Windows和Linux上,关闭所有窗口通常会完全退出一个应用程序。
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
// 除了 macOS 外,当所有窗口都被关闭的时候退出程序。
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') app.quit()
})
})
四、配置顶部菜单
1.配置顶部菜单
// 配置顶部菜单
const template = [
{
label: '文件',
submenu: [
{
label: '新建文件',
},
{
label: '新建窗口',
},
{
label: '打开文件'
}
]
},
{
label: '关于'
}
];
// 构建自定义的菜单
const menu = Menu.buildFromTemplate(template);
// 设置为应用菜单
Menu.setApplicationMenu(menu);
2. 给菜单定义点击事件
1.打开新窗口
submenu: [
{
label: '新建文件',
},
{
label: '新建窗口',
click() {
const mainWindow = new BrowserWindow({
height: 500,
width: 500
});
// 将 index.html 加载进 BrowserWindow 实例
mainWindow.loadFile('./src/index.html');
}
},
{
label: '打开文件',
}
]
2.打开浏览器
shell
模块提供了集成其他桌面客户端的关联功能.
submenu: [
{
label: '反馈',
click() {
const mainWindow2 = new BrowserWindow({
height: 500,
width: 500
});
// app 内部打开网页
mainWindow2.loadURL('https://www.baidu.com/');
}
},
{
label: '关于',
click() {
// 点击打开浏览器
shell.openExternal('https://www.baidu.com/')
}
}
]
3. 抽离菜单定义
1.新建 menu.js 文件,将顶部菜单的定义都放到这个里面去就好了
// 配置顶部菜单
const { BrowserWindow, Menu, shell } = require('electron')
// 定义菜单模板
const template = [
{
label: '文件',
submenu: [
{
label: '新建文件',
},
{
label: '新建窗口',
click() {
const mainWindow = new BrowserWindow({
height: 500,
width: 500
});
// 将 index.html 加载进 BrowserWindow 实例
mainWindow.loadFile('./src/index.html');
}
},
{
label: '打开文件',
}
]
},
{
label: '帮助',
submenu: [
{
label: '反馈',
click() {
const mainWindow2 = new BrowserWindow({
height: 500,
width: 500
});
// app 内部打开网页
mainWindow2.loadURL('https://www.baidu.com/');
}
},
{
label: '关于',
click() {
// 点击打开浏览器
shell.openExternal('https://www.baidu.com/')
}
}
]
}
];
// 构建自定义的菜单
const menu = Menu.buildFromTemplate(template);
// 设置为应用菜单
Menu.setApplicationMenu(menu);
2.在 main.js 入口文件中引入顶部菜单定义文件 menu.js 即可
const { app, BrowserWindow } = require('electron')
// 热加载
const reloader = require('electron-reloader');
reloader(module);
// 创建窗口并加载index.html
const createWindow = () => {
const mainWindow = new BrowserWindow({
height: 500,
width: 500
});
// 将 index.html 加载进 BrowserWindow 实例
mainWindow.loadFile('./src/index.html');
// 配置顶部菜单
require('./menu')
};
五、只关闭默认的顶部菜单 保留最大化最小化和关闭按钮
// 只关闭默认的顶部菜单
mainWindow.setMenu(null);
六、自定义顶部菜单 包括自定义最大化最小化和关闭按钮
1.通过配置 frame 属性创建无边框窗口
const createWindow = () => {
const mainWindow = new BrowserWindow({
height: 500,
width: 500,
frame: false //去掉顶部导航 去掉关闭按钮 最大化最小化按钮
});
// 将 index.html 加载进 BrowserWindow 实例
mainWindow.loadFile('./src/index.html');
};
2.自定义菜单
<!-- 顶部导航栏 -->
<div class="custom-menu">
<ul>
<li>新建文件</li>
<li>帮助</li>
<li>联系我们</li>
</ul>
</div>
* {
margin: 0;
padding: 0;
}
.custom-menu {
height: 43px;
width: 100%;
background: #030303;
-webkit-app-region: drag;
}
.custom-menu ul {
list-style: none;
margin-left: 5px;
}
.custom-menu ul li {
float: left;
line-height: 43px;
padding-left: 5px;
padding-right: 5px;
font-size: 11px;
color: aliceblue;
}
3.配置窗口可拖拽
可拖拽
-webkit-app-region: drag;
不可拖拽
-webkit-app-region: no-drag
当前效果:
4.给自定义菜单定义点击事件
这个区别于第四章配置的顶部菜单的点击事件
第四章那个是在主进程中定义点击事件的
这个是在渲染进程中自定义的
1.打开新窗口
// html
<li class="new-window">新建文件</li>
// js
// remote 通过remote使用主进程的方法
const { remote: {BrowserWindow} } = require('electron')
const newWindow = document.querySelector('.new-window')
newWindow.onclick = function () {
new BrowserWindow({
width: 200,
height: 300
})
}
在 main.js 中配置 webPreferences,从而可以在 html 中使用 node 方法