Electron: создание и управление окнами
В Electron окна (Window) являются основным средством взаимодействия между приложением и пользователем.
Все видимые интерфейсы работают впроцессе рендеринга, а за создание и управление этими окнами отвечаетглавный процесс.
Создание и управление окнами
Electron с помощьюBrowserWindowкласса для создания окон.
В основном процессе новое окно определяется следующим образом:
Пример
let mainWindow = new BrowserWindow({
width: 1200,
height: 800,
show: false, // Ждать, пока страница не будет готова, прежде чем отображать
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
},
})
Параметры конфигурации BrowserWindow
width/height: Ширина и высота окна.minWidth/minHeight: Ограничение минимального размера.resizable: Разрешено ли изменение размера.fullscreen/fullscreenable: Переходить ли в полноэкранный режим.frame: Показывать ли системную строку заголовка (часто отключается при использовании пользовательской строки заголовка).transparent: Прозрачное окно (позволяет достичь таких эффектов, как матовое стекло, парение и т. д.).alwaysOnTop: Всегда ли окно находится поверх других окон.
Размер окна, положение и состояние
Состоянием окна можно управлять через API:
mainWindow.maximize() // 最大化
mainWindow.minimize() // 最小化
mainWindow.restore() // 还原
mainWindow.setBounds({ x: 100, y: 100, width: 800, height: 600 }) // 调整位置和大小
Также можно прослушивать изменения окна:
mainWindow.on('resize', () => console.log('窗口尺寸变化'))
mainWindow.on('move', () => console.log('窗口移动'))
Окна без рамки и настраиваемая строка заголовка
Настройкиframe: falseПосле этого можно настроить область строки заголовка и имитировать перетаскивание с помощью CSS и JS:
.titlebar {
-webkit-app-region: drag;
}
Учтите, что неперетаскиваемые области (например, кнопки) следует добавлять с помощью:
.titlebar {
-webkit-app-region: drag;
}
Прослушивание событий окна
mainWindow.on('close', (e) => {
e.preventDefault()
mainWindow.hide()
})
Распространённые события включают:
ready-to-show: Страница завершила загрузку, и её можно безопасно отображать.focus/blur: Окно получает или теряет фокус.closed: Окно было уничтожено.
Загрузка содержимого страницы
Окна Electron могут загружать локальные HTML-файлы или удалённые веб-сайты.
Загрузка локальных HTML-файлов
mainWindow.loadFile('index.html')
Загрузка удалённого URL
mainWindow.loadURL('https://example.com')
Использование фронтенд-фреймворков
Если вы используете современные фреймворки, такие как Vue, React или Angular, вы можете загрузить собранные статические файлы в окно:
mainWindow.loadFile(path.join(__dirname, 'dist/index.html'))
Или загрузить локальный сервис в режиме разработки:
mainWindow.loadURL('http://localhost:5173')
Взаимодействие между окнами
В многоконных приложениях может потребоваться передавать данные между окнами или управлять поведением.
Связь родительского и дочернего окон
Можно указать при создании нового окнаparent:
let child = new BrowserWindow({
parent: mainWindow,
modal: true, // 模态窗口
width: 400,
height: 300,
})
Когда родительское окно закрывается, дочерние окна также автоматически закрываются.
Совместное использование данных между окнами
Вы можете использовать главный процесс в качестве посредника для передачи данных между различными процессами рендеринга или использовать глобальные объекты илиipcMain / ipcRenderer。
Передача сообщений между окнами
Главный процесс может напрямую управлять целевым окном:
child.webContents.send('update-data', someData)
Получение в дочернем окне:
const { ipcRenderer } = require('electron')
ipcRenderer.on('update-data', (event, data) => {
console.log(data)
})
Оптимизация интерфейса
Экран-заставка
Когда главное окно загружается медленно, можно сначала показать лёгкое окно-заставку:
const splash = new BrowserWindow({ width: 400, height: 300, frame: false })
splash.loadFile('splash.html')
mainWindow.once('ready-to-show', () => {
splash.close()
mainWindow.show()
})
Оптимизация отображения окна
Распространённые методы предотвращения мерцания белого экрана включают:
- Использование
show: falseСоздайте окно и после завершения загрузки,show()。 - Установите цвет фона на отрисовываемой странице.
- Предварительно загружайте ресурсы (иконки, шрифты, стили).
Методы предотвращения мерцания
- Включите ускорение GPU или отключите аппаратное ускорение (в зависимости от ситуации).
- Избегайте сложных анимаций или градиентов в CSS.
- Используйте двойную буферизацию рендеринга для уменьшения дрожания при отрисовке.
Многооконное приложение Electron (включая страницу-заставку, основной интерфейс и дочерние окна)
Структура каталогов
my-electron-app/ ├── package.json ├── main.js # 主进程入口 ├── preload.js # 预加载脚本 ├── splash.html # 启动画面 ├── index.html # 主窗口页面 ├── child.html # 子窗口页面 └── renderer.js # 渲染进程逻辑
main.js (главный процесс)
Пример
const path = require('path')
let mainWindow, splash, childWindow
function createSplash() {
splash = new BrowserWindow({
width: 400,
height: 300,
frame: false,
transparent: true,
alwaysOnTop: true,
})
splash.loadFile('splash.html')
}
function createMainWindow() {
mainWindow = new BrowserWindow({
width: 1200,
height: 800,
show: false,
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
},
})
mainWindow.loadFile('index.html')
// Показать после завершения загрузки страницы
mainWindow.once('ready-to-show', () => {
if (splash) splash.close()
mainWindow.show()
})
mainWindow.on('closed', () => (mainWindow = null))
}
function createChildWindow() {
childWindow = new BrowserWindow({
parent: mainWindow,
modal: true,
width: 400,
height: 300,
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
},
})
childWindow.loadFile('child.html')
}
// Межпроцессное взаимодействие
ipcMain.on('open-child', () => {
if (!childWindow) createChildWindow()
})
ipcMain.handle('get-app-info', () => {
return {
name: app.getName(),
version: app.getVersion(),
}
})
app.on('ready', () => {
createSplash()
setTimeout(() => createMainWindow(), 1500)
})
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') app.quit()
})
preload.js(скрипт предзагрузки)
const { contextBridge, ipcRenderer } = require('electron')
contextBridge.exposeInMainWorld('electronAPI', {
openChild: () => ipcRenderer.send('open-child'),
getAppInfo: () => ipcRenderer.invoke('get-app-info'),
})
index.html (главное окно)
Пример
<html lang="ru">
<head>
<meta charset="UTF-8" />
<title>главное окно</title>
<style>
body { font-family: sans-serif; text-align: center; margin-top: 100px; }
button { padding: 10px 20px; font-size: 16px; cursor: pointer; }
</style>
</head>
<body>
<h1>Добро пожаловать в приложения Electron</h1>
<p id="info"></p>
<button id="open">Открыть дочернее окно</button>
<script src="renderer.js"></script>
</body>
</html>
child.html (дочернее окно)
Пример
<html lang="zh">
<head>
<meta charset="UTF-8" />
<title>дочернее окно</title>
<style>
body { font-family: sans-serif; text-align: center; margin-top: 100px; }
</style>
</head>
<body>
<h2>Это дочернее окно</h2>
<p>Может принимать команды из главного окна</p>
</body>
</html>
splash.html (Экран-заставка)
Пример
<html lang="zh">
<head>
<meta charset="UTF-8" />
<title>Загрузка...</title>
<style>
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background: linear-gradient(135deg, #8EC5FC, #E0C3FC);
font-family: sans-serif;
}
h1 {
font-size: 28px;
color: #333;
}
</style>
</head>
<body>
<h1>Приложение запускается, пожалуйста, подождите...</h1>
</body>
</html>
renderer.js (логика рендеринга)
Пример
const btn = document.getElementById('open')
// Показать информацию о приложении
window.electronAPI.getAppInfo().then((appInfo) => {
info.textContent =`Имя приложения:${appInfo.name}| Версия: ${appInfo.version}`
})
// Открыть дочернее окно
btn.addEventListener('click', () => {
window.electronAPI.openChild()
})
Процесс после запуска выглядит следующим образом:
- Показывать при запускеЭкран-заставка(
splash.html)。 - После завершения загрузки автоматически закрыть страницу-заставку и показатьглавное окно。
- Главное окно может открыватьдочернее окнос помощью кнопки, демонстрируя функциональность IPC-взаимодействия.
- Главное окно используетPreload для безопасного предоставления API, предотвращая прямой доступ к Node.js.
- Все окна используютпрослушивание событий、отложенное отображениеи другие стратегии оптимизации, чтобы избежать белых экранов и мерцания.