一、改变窗口大小时的过渡
直接 setSize()
会直接看到大小变化,放在普通场景算正常,但是如果类似从登录界面切换到主界面,这时候直接变化大小看起来很奇怪,所以需要做点处理过渡一下。
当然,登录窗口和主窗口你可以用两个
BrowserWindow
实例来实现,这里只说只用一个窗口的方式
第一步,初始化窗口的函数
export const initLoginWindow = (windowObj) => {
windowObj.setTitle('登录');
windowObj.setSize(400, 300);
windowObj.setMinimumSize(400, 300);
windowObj.setResizable(false);
windowObj.setMaximizable(false);
windowObj.center();
};
export const initMainWindow = (windowObj) => {
windowObj.setTitle('xxx客户端');
windowObj.setSize(1440, 900);
windowObj.setMinimumSize(1024, 768);
windowObj.setResizable(true);
windowObj.setMaximizable(true);
windowObj.center();
};
第二步,新建监听,用于设置窗口信息,延迟展示窗口
function delayShowWindow(initFn, delay) {
mainWindow.setOpacity(0);
initFn(mainWindow);
// 在最小化之后修改size会无效,所以要在最小化之前修改大小
mainWindow.minimize();
setTimeout(() => {
mainWindow.setOpacity(1);
mainWindow.show();
mainWindow.focus();
}, delay);
}
ipcMain.on('showMainWindow', (event, delay=500) => {
if (delay) {
delayShowWindow(initMainWindow, delay);
} else {
initMainWindow(mainWindow);
}
});
ipcMain.on('showLoginWindow', (event, delay) => {
if (delay) {
delayShowWindow(initLoginWindow, delay);
} else {
initLoginWindow(mainWindow);
}
});
关键代码在 delayShowWindow
,先改成透明,然后设置大小、标题等等,然后执行最小化,最后延迟展示。
注意:mainWindow.setOpacity(0)
如果改用 mainWindow.hide()
,某些时候会导致 setSize()
失效
二、单击托盘时展示窗口到顶层,但不是一直在顶层
appTray.on('click', () => {
// 只要点击就展示,符合大部分软件操作方式
mainWindow.show();
// 展示到所有窗口最上层
mainWindow.setAlwaysOnTop(true);
const onTopTimer = setTimeout(() => {
mainWindow.setAlwaysOnTop(false);
clearTimeout(onTopTimer);
}, 500);
});
利用 setAlwaysOnTop
先置顶后取消
三、托盘闪烁
appTray.setImage(iconMessagePath);
let count = 0;
flashTrayTimer = setInterval(function () {
count++;
if (count % 2 === 0) {
appTray.setImage(iconTransparentPath);
} else {
appTray.setImage(iconMessagePath);
}
}, 600);
间隔切换透明和正常的托盘图标
四、使用vue-devtool
有科学上网的可以无视,不能访问github的可以去百度、优快云找 .crx 文件,修改后缀为 .zip 然后解压,放到项目里,然后安装:
import { app, session } from 'electron';
import * as path from 'path';
const isDevelopment = process.env.NODE_ENV !== 'production';
app.on('ready', () => {
if (isDevelopment && !process.env.IS_TEST) {
// 本地安装
const vueDevtoolPath = path.join(__dirname, '../assets/vue-devtool-6.1.4_0');
session.defaultSession.loadExtension(vueDevtoolPath,
// allowFileAccess is required to load the devtools extension on file:// URLs.
{ allowFileAccess: true }
).catch(e => {
console.error('Vue Devtools failed to install:', e.toString());
});
}
});
五、新建项目
建议用 vue-cli-plugin-electron-builder
六、最小化时隐藏任务栏展示,打开窗口时还原
// 最小化
mainWindow.minimize();
mainWindow.setSkipTaskbar(true);
// 展示窗口时显示到任务栏
mainWindow.on('show', () => {
mainWindow.setSkipTaskbar(false);
});
七、使用比较安全的架构设计
- 使用
contextIsolation:true
,取消renderer进程使用nodenodeIntegration:false
- 所有renderer进程需要用到main进程东西的地方都用
window.预加载时暴露的全局对象
来操作,如
background.js
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
preload: path.join(__dirname, 'preload.js')
}
init-ipc.js
ipcMain.on('windowQuit', () => {
mainWindow.destroy();
app.quit();
});
ipcMain.on('windowAction', (event, action) => {
switch (action) {
case 'minimize':
mainWindow.minimize();
mainWindow.setSkipTaskbar(true);
break;
case 'maximize':
if (mainWindow.isMaximized()) {
mainWindow.unmaximize();
} else {
mainWindow.maximize();
}
break;
case 'close':
mainWindow.close();
break;
default:
break;
}
event.returnValue = JSON.stringify({
isMaximized: mainWindow.isMaximized(),
isMinimized: mainWindow.isMinimized()
});
});
preload.js
import { contextBridge, ipcRenderer } from 'electron';
contextBridge.exposeInMainWorld('mainAPI', {
// 用户数据目录
userDataPath: () => ipcRenderer.sendSync('userData'),
// 窗口行为:最小化、最大化、还原、关闭
windowAction: (action) => JSON.parse(ipcRenderer.sendSync('windowAction', action))
});
contextBridge.exposeInMainWorld('systemAPI', {
// 获取是否开启启动
getAutoStartValue: () => ipcRenderer.invoke('sob:getAutoStartValue'),
// 设置开机自动启动
enableAutoStart: () => ipcRenderer.invoke('sob:enableAutoStart'),
// 取消开机自动启动
disableAutoStart: () => ipcRenderer.invoke('sob:disableAutoStart')
});
renderer进程
// 切换最大化和还原,并获取最新状态
const { isMaximized } = window.mainAPI.windowAction('maximize');
// 设置开机启动
window.systemAPI.enableAutoStart().then(() => console.log('设置成功'))