这是我参与11月更文挑战的第2天,活动详情查看:2021最后一次更文挑战
主要在于目前开发的项目是electron+vue的技术,项目进度过半,但是开发的无比艰辛。难点解决不了,但是一些基础的东西还是有很深理解的。
窗口通信
electron项目中各窗口之间有多种通信方式,这里介绍其中一种ipcMain/ipcRenderer方式。
// A窗口,多为在方法里触发
createGroup() {
ipcRenderer.send("add", "234");
}
// background.js
ipcMain.on("add", (event, arg) => {
win.webContents.send("addReply", arg)
})
// B窗口,在生命周期中接收
created() {
ipcRenderer.on("addReply", (event, arg) => {
console.log(arg);
});
}
但是在项目中出现了一种情况:on方式监听所触发的事件会有多次触发的情况!!! 在网上百度了很久,查到的结果都是将on改成once。但是我修改了以后还是多次触发的情况,希望有大佬看到的话,能帮忙解答下
窗口拖拽
遇到两种情况:
- 窗口设置movable属性为true;
- frame为false时候添加拖动样式
设置拖拽属性
win = new BrowserWindow({
...
movable: true,
...
})
设置拖拽样式
主窗口设置 frame: false,后,整个窗口不可拖动,因为其关闭了window自带的关闭等功能以及工具栏。可以通过修改修改样式元素方式使元素可以拖动。
.ele_drag {
-webkit-app-region: drag; /* 让元素可拖动,设置了drag的元素不可点击 */
}
.no_drag {
-webkit-app-region: no-drag; /* 设置了drag的元素将不可点击,故设置no-drag,让元素可点击 */
}
- drag一般设置给顶层header元素,使得header部分点击可拖动,但设置了以后会导致header内部元素不可点击,所以需要给可点击元素添加no-drag样式
- no-drag设置给可点击元素
系统托盘
import {Tray, Menu, nativeImage} from 'electron'
// 托盘图标路径处理
const icon = nativeImage.createFromPath(
path.join(__static, './favicon.ico')
)
tray = new Tray(icon)
tray.setToolTip('electron demo is running')
tray.setTitle('electron demo')
tray.on('right-click', () => {
// 右键菜单模板
const tempate = [
{
label: '退出',
click: () => app.quit(),
},
]
//通过 Menu 创建菜单
const menuConfig = Menu.buildFromTemplate(tempate)
// 让我们的写的托盘右键的菜单替代原来的
tray.popUpContextMenu(menuConfig)
})
tray.on('click', () => {
// 这里来控制窗口的显示和隐藏
if (win.isVisible()) {
win.hide()
} else {
win.show()
}
})
窗口创建配置
基础配置
import {BrowserWindow} from 'electron'
let win = new BrowserWindow({
width: 450, // 窗口宽度
height: 435, // 窗口高度
frame: false, // 窗口是否带边框(工具信息)
movable: true, // 窗口是否可移动
webPreferences: {
nodeIntegration: true,
contextIsolation: false,
enableRemoteModule: true // 是否启用remote模块
}
})
加载配置
if (process.env.WEBPACK_DEV_SERVER_URL) {
await win.loadURL(process.env.WEBPACK_DEV_SERVER_URL)
// calendarWin.loadURL(winURL + '/Friendinformation') // 子窗口
if (!process.env.IS_TEST) win.webContents.openDevTools() // 开启窗口开发调试工具
} else {
createProtocol('app')
win.loadURL('app://./index.html')
// calendarWin.loadURL('app://./index.html#Friendinformation') // 子窗口
}
窗口的大小切换
remote方式
import {remote} from 'electron'
// 缩小
remote.getCurrentWindow().minimize();
// 放大
remote.getCurrentWindow().maximize();
// 判断是否处于最大化
remote.getCurrentWindow().isMaximized()
// 恢复
remote.getCurrentWindow().restore();
主进程控制
// 缩小
mainWindow.minimize();
// 放大
mainWindow.maximize();
// 判断是否处于最大化
mainWindow.isMaximized();
// 恢复
mainWindow.restore();
二级窗口关闭
通过elecctron的remote模块,可以获取到当前窗口的实例对象,从而执行close方法
import { remote } from "electron";
closeWin() {
remote.getCurrentWindow().close();
}
主窗口关闭
由于设置了主窗口关闭不退出而是隐藏在系统托盘,所以执行的是窗口实例对象的hide方法
// vue文件中
import { ipcRenderer} from "electron";
hideWin() {
ipcRenderer.send("hide")
// background.js
ipcMain.on("hide",()=>win.hide())
也可以采用remote模块的方式执行hide方法
import { remote } from "electron";
hideWin() {
remote.getCurrentWindow().hide();
}
主窗口退出
退出方法有几种:window.close()、window.destory()、app.quit()、app.exit()
-
window.close():尝试关闭窗口
-
window.destory():强制关闭窗口
-
app.quit():如果所有窗口已关闭,直接触发quit事件。
- 否则会先触发befrore-quit,再关闭所有窗口,最后触发will-quit事件。
- 在before-quit、will-quit中调用event.preventDefault();在window.close()的回调函数中组织窗口关闭,都可以使得退出失败
-
app.exit():直接退出窗口,没有任何其他操作