Electron基础了解和用法总结
作者:互联网
Electron流程
- Electron 继承了来自 Chromium 的多进程架构,这使得此框架在架构上非常相似于一个现代的网页浏览器
为什吗不是单一的进程
- 网页浏览器是个极其复杂的应用程序。 除了显示网页内容的主要能力之外,他们还有许多次要的职责,例如:管理众多窗口 ( 或 标签页 ) 和加载第三方扩展。在早期,浏览器通常使用单个进程来处理所有这些功能。 虽然这种模式意味着您打开每个标签页的开销较少,但也同时意味着一个网站的崩溃或无响应会影响到整个浏览器。
多进程模型
为了解决这个问题,Chrome 团队决定让每个标签页在自己的进程中渲染, 从而限制了一个网页上的有误或恶意代码可能导致的对整个应用程序造成的伤害。 然后用单个浏览器进程控制这些標籤頁进程,以及整个应用程序的生命周期。 下方来自 Chrome 漫画 的图表可视化了此模型:
Electron 应用程序的结构非常相似。 作为应用开发者,您控制着两种类型的进程:主进程和渲染器。 这些类似于上面概述的 Chrome 自己的浏览器和其渲染器进程。
主进程
每个 Electron 应用都有一个单一的主进程(app),作为应用程序的入口点。 主进程在 Node.js 环境中运行,这意味着它具有 require 模块和使用所有 Node.js API 的能力。主进程的主要目的是使用 BrowserWindow 模块创建和管理应用程序窗口。
预加载脚本
预加载(preload)脚本包含了那些执行于渲染器进程中,且先于网页内容开始加载的代码 。 这些脚本虽运行于渲染器的环境中,却因能访问 Node.js API 而拥有了更多的权限。
预加载脚本可以在 BrowserWindow 构造方法中的 webPreferences 选项里被附加到主进程。
const { BrowserWindow } = require('electron')
//...
const win = new BrowserWindow({
webPreferences: {
preload: 'path/to/preload.js'
}
})
- 虽然预加载脚本与其所附加的渲染器在全局共享着一个 window 变数,但不能从中直接附加任何变数到 window 之中,
window.myAPI = {
desktop: true
};
console.log(window.myAPI)// => undefined - 语境隔离(Context Isolation)意味着预加载脚本与渲染器的主要运行环境是隔离开来的,以避免泄漏任何具特权的 API 到您的网页内容代码中。取而代之,我们將使用 contextBridge 模块来安全地实现交互:
const { contextBridge } = require('electron')
contextBridge.exposeInMainWorld('myAPI', {
desktop: true
})
console.log(window.myAPI)
// => { desktop: true }
main.js 基础配置
let electron = require('electron'); // 引入electron模块
const path = require('path')
const process = require('process');
const { app, BrowserWindow } = require('electron');
// app 它控制应用程序的事件生命周期。
// BrowserWindow 它创建和管理应用程序 窗口。
let mainWindow = null; // 声明要打开的主窗口
//在 Electron 中,只有在 app 模块的 ready 事件被激发后才能创建浏览器窗口。 您可以通过使用 app.whenReady() API来监听此事件。 在whenReady()成功后调用createWindow()。
function createWindew (){
mainWindow = new BrowserWindow({
width: 800, // 设置打开的窗口大小
height: 800,
webPreferences: {
// 开启node
nodeIntegration: true,//防止使用require引用报错
// 开启remote
enableRemoteModule: true,
contextIsolation: false //防止使用require引用报错
preload: path.join(__dirname, 'preload.js')//预加载 预加载脚本在渲染器进程加载之前加载,并有权访问两个 渲染器全局 (例如 window 和 document) 和 Node.js 环境
//__dirname 字符串指向当前正在执行脚本的路径 (在本例中,它指向你的项目的根文件夹)。
// path.join API 将多个路径联结在一起, 创建一个跨平台的路径字符串。
}
});
mainWindow.loadFile('xxxx.html'); // 加载哪个页面
mainWindow.on('closed', () => { // 监听关闭事件,把主窗口设置为null,否则内存会占用越来越多
mainWindow = null;
})
}
//关闭所有窗口时退出应用(Windows & Linux)
//process.platform :获取操作系统平台信息
//darwin 苹果出的一个操作系统
app.on('window-all-closed', function() {
// 除了 macOS 外,当所有窗口都被关闭的时候退出程序。 因此,通常对程序和它们在
// 任务栏上的图标来说,应当保持活跃状态,直到用户使用 Cmd + Q 退出。
if (process.platform !== 'darwin') app.quit()
})
//Linux 和 Windows 应用在没有窗口打开时退出macOS 应用通常即使在没有打开任何窗口的情况下也继续运行,并且在没有窗口可用的情况下激活应用时会打开新的窗口。
//为了实现这一特性,监听 app 模块的 activate 事件。如果没有任何浏览器窗口是打开的,则调用 createWindow() 方法.因为窗口无法在 ready 事件前创建,你应当在你的应用初始化后仅监听 activate 事件。 通过在您现有的 whenReady() 回调中附上您的事件监听器来完成这个操作。
// 这段程序将会在 Electron 结束初始化
// 和创建浏览器窗口的时候调用
// 部分 API 在 ready 事件触发后才能使用。
app.whenReady().then(() => {
createWindow()
app.on('activate', function () {
// 通常在 macOS 上,当点击 dock 中的应用程序图标时,如果没有其他
// 打开的窗口,那么程序会重新创建一个窗口。
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
使用remote模块
- 该remote模块在 Electron 12 中被弃用,将在 Electron 14 中移除。 由**@electronic/remote**模块替代;
- 作用:通俗讲就是 remote 模块让仅在主进程中可用的一些模块,比如app, 通知,dialog,渲染进程也可以调用 ;
使用:
// 1. 先安装 npm install --save @electron/remote
//2. 主进程中
require('@electron/remote/main').initialize();
require('@electron/remote/main').enable(mainWindow.webContents);//添加原因是不加会有@electron/remote is disabled for this WebContentsCall require("@electron/remote/main").enable(webContents) to enable it.报错出来,但是文档中缺没有标出很奇怪.
//3. 渲染进程中使用
const { BrowserWindow } = require('@electron/remote')
在渲染进程中打开新窗口几种方式;
- 1.window.open(url[, frameName][, features])
- 例如 :window.open(’./render/test3.html’,’_blank’,‘top=500,left=200,frame=false,nodeIntegration=no’);
- 2 使用remote导入BrowserWindow 创
- 例如:
newWin = new BrowserWindow({ width: 600, height: 600, })
菜单栏内容及自定义菜单栏
主要常用功能
- 点击File exit 关闭程序
- view =>reload 刷新页面 view=> Toggle Developer Tools 打开控制台
自定义菜单栏
- 自定义菜单文件
//menu.js
const { Menu, BrowserWindow } = require('electron');
let template = [{
label: '中国富婆通讯录',
submenu: [{
label: '北京地区富婆名单',
// 加入click事件
click: () => {
win = new BrowserWindow({
width: 400,
height: 400,
webPreferences: { nodeIntegration: true }
})
win.loadFile('xxx.html')
win.on('closed', () => {
win = null
})
}
},
{ label: '河北通讯录' },
{label:"基尼太美"}
]
},
{
label: '撩妹 必备技能 ',
submenu: [
{ label: '唱跳rap' },
{ label: '篮球' }
]
}
]
// 设置菜单
let m = Menu.buildFromTemplate(template)
Menu.setApplicationMenu(m) //设置
- main.js引入
//入口文件引入你自定义的菜单信息
function createWindow() {
require('./main/menu.js') // 自定义菜单文件
mainWindow = new BrowserWindow({
width: 800, // 设置打开的窗口大小
height: 800,
webPreferences: {
nodeIntegration: true,
// 开启remote
enableRemoteModule: true,
contextIsolation: false,
preload: path.join(__dirname, 'preload.js')
//__dirname 字符串指向当前正在执行脚本的路径 (在本例中,它指向你的项目的根文件夹)。
// path.join API 将多个路径联结在一起, 创建一个跨平台的路径字符串。
}
});
mainWindow.loadFile('demo1.html'); // 加载哪个页面
require('@electron/remote/main').initialize();
require('@electron/remote/main').enable(mainWindow.webContents)
mainWindow.on('closed', () => { // 监听关闭事件,把主窗口设置为null,否则内存会占用越来越多
mainWindow = null;
});
mainWindow.webContents.openDevTools()
}
标签:总结,remote,require,electron,用法,BrowserWindow,Electron,进程,窗口 来源: https://blog.csdn.net/weixin_48366131/article/details/121674316