在 Electron 中,有主进程和渲染进程
主进程:
在Node.js环境中运行—意味着能够使用require
模块并使用所有Node.js API
渲染进程:
每个electron应用都会为每个打开的BrowserWindow
(与每个网页嵌入)生成一个单独的渲染器进程。
windows 中展示的界面通过渲染器进程渲染且一个应用可以有多个渲染进程
因此,一个浏览器窗口的所有的用户界面和应用功能,都应该是在网页开发上使用相同的工具和规范来写(如html,css,js)
因此这也意味着渲染器无权直接访问require
或其他Node.js API.
BrowserWindow
是一个只能在主进程中使用的类,而不能直接在渲染进程中创建。因此,当你在渲染进程中尝试直接使用 BrowserWindow
创建新窗口时,会出现 BrowserWindow is not a constructor
的错误。
以下是几种解决方法:
在渲染进程中通过 IPC 向主进程发送消息,主进程接收到消息后创建新窗口。这是推荐的方式,因为它符合 Electron 的设计。
main.js
)const { app, BrowserWindow, ipcMain } = require('electron');
let mainWindow = null;
const createWindow = () => {
mainWindow = new BrowserWindow({
webPreferences: {
nodeIntegration: true,
contextIsolation: false,
},
});
mainWindow.loadFile('index.html');
};
app.on('ready', createWindow);
ipcMain.on('create-new-window', () => {
const newWindow = new BrowserWindow({
width: 400,
height: 300,
webPreferences: {
nodeIntegration: true,
contextIsolation: false,
},
});
newWindow.loadFile('new-window.html');
});
index.html
)<button id="newWindow">创建窗口button>
<script>
const { ipcRenderer } = require('electron');
document.getElementById('newWindow').addEventListener('click', () => {
ipcRenderer.send('create-new-window');
});
script>
@electron/remote
模块虽然 Electron 官方不推荐使用 @electron/remote
,但可以通过它在渲染进程中直接创建 BrowserWindow
。
const { app, BrowserWindow } = require('electron');
require('@electron/remote/main').initialize();
let mainWindow = null;
const createWindow = () => {
mainWindow = new BrowserWindow({
webPreferences: {
enableRemoteModule: true,
contextIsolation: false,
},
});
require('@electron/remote/main').enable(mainWindow.webContents);
mainWindow.loadFile('index.html');
};
app.on('ready', createWindow);
const { BrowserWindow } = require('@electron/remote');
document.getElementById('newWindow').addEventListener('click', () => {
const newWindow = new BrowserWindow({
width: 400,
height: 300,
});
newWindow.loadFile('new-window.html');
});
window.open
如果需要从渲染进程直接打开新窗口,可以使用 window.open
方法,并通过 webContents.setWindowOpenHandler
在主进程中自定义窗口的创建。
const { app, BrowserWindow } = require('electron');
let mainWindow = null;
const createWindow = () => {
mainWindow = new BrowserWindow({
webPreferences: {
nodeIntegration: true,
contextIsolation: false,
},
});
mainWindow.loadFile('index.html');
mainWindow.webContents.setWindowOpenHandler((details) => {
const newWindow = new BrowserWindow({
width: 400,
height: 300,
webPreferences: {
nodeIntegration: true,
contextIsolation: false,
},
});
newWindow.loadURL(details.url);
return { action: 'deny' }; // 阻止默认行为
});
};
app.on('ready', createWindow);
<button id="newWindow">创建窗口button>
<script>
document.getElementById('newWindow').addEventListener('click', () => {
window.open('new-window.html', '_blank');
});
script>
@electron/remote
的安全性和未来兼容性。