Skip to content

Commit f8c0455

Browse files
committed
refactor: 重构background.js
- 抽离创建窗口代码到windows/mainWindow.js中 - tray系统托盘引入的主窗口代码从mainWindow.js中引入 - 更新README.md文档
1 parent 8f6b2bd commit f8c0455

File tree

4 files changed

+107
-86
lines changed

4 files changed

+107
-86
lines changed

README.md

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,6 @@
11
# Electron Template
22

3-
Electron Template 是一个基于 Electron 框架的开源项目模板,它可以帮助开发者更快地创建 Electron 应用程序。该模板提供了一组常用的功能和结构,如主进程、渲染进程、菜单栏、快捷键、错误处理和日志记录等,以及一些常用的第三方库和工具。使用 Electron Template,开发者可以专注于自己的业务逻辑,而不必从头开始搭建 Electron 应用程序的框架。
4-
5-
主要特点包括:
6-
7-
- 简单易用:使用 Electron Template,开发者可以快速创建一个可运行的 Electron 应用程序,只需几行命令即可完成。
8-
- 可定制性强:Electron Template 的结构清晰,代码易于理解和修改。开发者可以根据自己的需求,自由地添加、删除、修改功能。
9-
- 社区支持良好:Electron Template 是一个活跃的开源项目,拥有一个庞大的开发者社区。开发者可以在社区中获取支持和帮助,也可以贡献自己的代码和想法。
10-
11-
总之,如果你需要一个快速创建 Electron 应用程序的模板,Electron Template 是一个不错的选择。
3+
Electron Template 是一个基于 [vue-cli-plugin-electron-builder](https://github.com/nklayman/vue-cli-plugin-electron-builder) 框架的开源项目模板。
124

135
## 基于该模版开发的项目案例
146

@@ -28,8 +20,6 @@ npm install
2820
npm install --ignore-engines --legacy-peer-deps
2921
```
3022

31-
还有问题? [docs/FrequentlyAskedQuestions.md](docs/FrequentlyAskedQuestions.md)
32-
3323
### 启动项目
3424

3525
```

src/main/background.js

Lines changed: 10 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -7,63 +7,15 @@ import path from 'path';
77
import {handleSetTitle} from '@/main/utils/setTitle.js';
88
import {handleFileOpen} from '@/main/utils/openDialog.js';
99

10+
const {createWindow, setQuitting, getMainWindow} = require('@/main/windows/mainWindow.js');
11+
1012
const isDevelopment = process.env.NODE_ENV !== 'production';
1113

1214
// Scheme must be registered before the app is ready
1315
protocol.registerSchemesAsPrivileged([{scheme: 'app', privileges: {secure: true, standard: true}}]);
1416

15-
const windowManager = {
16-
mainWindow: null
17-
};
18-
19-
let isQuitting = false;
20-
21-
// let mainWindow;
22-
async function createWindow() {
23-
// Create the browser window.
24-
windowManager.mainWindow = new BrowserWindow({
25-
width: 800,
26-
height: 600,
27-
autoHideMenuBar: true, // 自动隐藏菜单
28-
// eslint-disable-next-line no-undef
29-
icon: path.join(__static, `icons/${process.platform === 'win32' ? 'win/icon.ico' : 'png/icon.png'}`),
30-
webPreferences: {
31-
// eslint-disable-next-line no-undef
32-
preload: path.join(__dirname, 'mainWindow.js'),
33-
// Use pluginOptions.nodeIntegration, leave this alone
34-
// See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info
35-
nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,
36-
contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION
37-
}
38-
});
39-
40-
windowManager.mainWindow.on('show', () => {
41-
// windowManager.mainWindow.setSkipTaskbar(false);
42-
});
43-
44-
windowManager.mainWindow.on('close', (event) => {
45-
if (!isQuitting) {
46-
// 关闭窗口 不退出应用
47-
event.preventDefault();
48-
windowManager.mainWindow.hide();
49-
// mainWindow.setSkipTaskbar(true);
50-
}
51-
// 如果 isQuitting 为 true,则允许窗口关闭,从而使应用退出
52-
});
53-
54-
if (process.env.WEBPACK_DEV_SERVER_URL) {
55-
// Load the url of the dev server if in development mode
56-
await windowManager.mainWindow.loadURL(process.env.WEBPACK_DEV_SERVER_URL);
57-
if (!process.env.IS_TEST) windowManager.mainWindow.webContents.openDevTools();
58-
} else {
59-
createProtocol('app');
60-
// Load the index.html when not in development
61-
windowManager.mainWindow.loadURL('app://./index.html');
62-
}
63-
}
64-
6517
app.on('before-quit', () => {
66-
isQuitting = true;
18+
setQuitting(true);
6719
});
6820

6921
// Quit when all windows are closed.
@@ -76,21 +28,19 @@ app.on('window-all-closed', () => {
7628
});
7729

7830
app.on('activate', () => {
79-
// On macOS it's common to re-create a window in the app when the
80-
// dock icon is clicked and there are no other windows open.
81-
if (BrowserWindow.getAllWindows().length === 0) {
82-
createWindow();
83-
} else {
84-
if (windowManager.mainWindow && !windowManager.mainWindow.isDestroyed()) {
85-
windowManager.mainWindow.show();
86-
}
31+
const mainWindow = getMainWindow({createIfNotFound: true});
32+
if (mainWindow.isMinimized()) {
33+
mainWindow.restore();
8734
}
35+
mainWindow.show();
8836
});
8937

9038
// This method will be called when Electron has finished
9139
// initialization and is ready to create browser windows.
9240
// Some APIs can only be used after this event occurs.
9341
app.on('ready', async () => {
42+
createProtocol('app');
43+
9444
if (isDevelopment && !process.env.IS_TEST) {
9545
// Install Vue Devtools
9646
try {
@@ -113,7 +63,7 @@ app.on('ready', async () => {
11363
// if (process.platform === 'win32') {
11464
// sdk.initialize();
11565
// }
116-
tray.initialize(windowManager);
66+
tray.initialize();
11767
settings.initialize();
11868

11969
if (process.platform === 'darwin') {

src/main/tray/index.js

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,24 @@
11
const {app, Menu, Tray, ipcMain, nativeImage, screen} = require('electron');
22
const path = require('path');
3+
const {getMainWindow} = require('@/main/windows/mainWindow.js');
34
let tray = null;
45

5-
exports.initialize = function initialize(windowManager) {
6-
tray = useTray(windowManager);
6+
exports.initialize = function initialize() {
7+
tray = useTray();
78
};
89

9-
function useTray(windowManager) {
10+
function useTray() {
1011
const iconPath = process.platform === 'win32' ? 'win/icon.ico' : 'png/icon.png';
1112

1213
const tray = new Tray(path.join(__static, `icons/${iconPath}`));
1314

14-
// const tray = new Tray(
15-
// path.join(__static, `icons/${process.platform === 'win32' ? 'win/icon.ico' : 'png/32x32.png'}`)
16-
// );
17-
1815
const template = [
1916
// {label: '退出', role: 'quit'}
2017
{
2118
label: '显示主页面',
2219
click: () => {
23-
if (windowManager.mainWindow && !windowManager.mainWindow.isDestroyed()) {
24-
windowManager.mainWindow.show();
25-
}
20+
const mainWindow = getMainWindow({createIfNotFound: true});
21+
mainWindow.show();
2622
}
2723
},
2824
{
@@ -34,9 +30,10 @@ function useTray(windowManager) {
3430
{
3531
label: '退出',
3632
click: () => {
37-
if (windowManager.mainWindow && !windowManager.mainWindow.isDestroyed()) {
33+
const mainWindow = getMainWindow({createIfNotFound: false});
34+
if (mainWindow && mainWindow.isDestroyed()) {
3835
// 1. 销毁主窗口
39-
windowManager.mainWindow.destroy();
36+
mainWindow.destroy();
4037
}
4138
// 2. 退出应用
4239
app.quit();
@@ -52,9 +49,8 @@ function useTray(windowManager) {
5249
if (process.platform === 'darwin') {
5350
tray.popUpContextMenu();
5451
} else {
55-
if (windowManager.mainWindow && !windowManager.mainWindow.isDestroyed()) {
56-
windowManager.mainWindow.show();
57-
}
52+
const mainWindow = getMainWindow({createIfNotFound: true});
53+
mainWindow.show();
5854
}
5955
};
6056

src/main/windows/mainWindow.js

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
const {BrowserWindow} = require('electron');
2+
const path = require('path');
3+
const log = require('@/main/log/index.js');
4+
5+
let isQuitting = false;
6+
let mainWindow;
7+
async function createWindow() {
8+
// Create the browser window.
9+
mainWindow = new BrowserWindow({
10+
width: 800,
11+
height: 600,
12+
autoHideMenuBar: true, // 自动隐藏菜单
13+
show: false,
14+
// eslint-disable-next-line no-undef
15+
icon: path.join(__static, `icons/${process.platform === 'win32' ? 'win/icon.ico' : 'png/icon.png'}`),
16+
webPreferences: {
17+
// eslint-disable-next-line no-undef
18+
preload: path.join(__dirname, 'mainWindow.js'),
19+
// Use pluginOptions.nodeIntegration, leave this alone
20+
// See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info
21+
nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,
22+
contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION
23+
}
24+
});
25+
26+
mainWindow.on('ready-to-show', () => {
27+
mainWindow.show();
28+
});
29+
30+
mainWindow.on('close', (event) => {
31+
if (!isQuitting) {
32+
// 关闭窗口 不退出应用
33+
event.preventDefault();
34+
mainWindow.hide();
35+
// mainWindow.setSkipTaskbar(true);
36+
}
37+
// 如果 isQuitting 为 true,则允许窗口关闭,从而使应用退出
38+
});
39+
40+
mainWindow.on('closed', () => {
41+
mainWindow = null;
42+
});
43+
44+
mainWindow.webContents.on('render-process-gone', (event, details) => {
45+
// 将窗口渲染进程崩溃事件的详细信息记录到日志文件
46+
log.error('Window render process crashed', {
47+
reason: details.reason,
48+
exitCode: details.exitCode
49+
});
50+
});
51+
52+
if (process.env.WEBPACK_DEV_SERVER_URL) {
53+
// Load the url of the dev server if in development mode
54+
await mainWindow.loadURL(process.env.WEBPACK_DEV_SERVER_URL);
55+
if (!process.env.IS_TEST) mainWindow.webContents.openDevTools();
56+
} else {
57+
// Load the index.html when not in development
58+
mainWindow.loadURL('app://./index.html');
59+
}
60+
61+
return mainWindow;
62+
}
63+
64+
function setQuitting(value) {
65+
isQuitting = value;
66+
}
67+
function getQuitting() {
68+
return isQuitting;
69+
}
70+
71+
function getMainWindow({createIfNotFound} = {createIfNotFound: true}) {
72+
// 不存在则会创建窗口
73+
if (createIfNotFound && (!mainWindow || (mainWindow && mainWindow.isDestroyed()))) {
74+
return createWindow();
75+
}
76+
77+
return mainWindow;
78+
}
79+
80+
module.exports = {
81+
createWindow,
82+
getMainWindow,
83+
setQuitting,
84+
getQuitting
85+
};

0 commit comments

Comments
 (0)