Electron中单例模式运行app的相关代码
"electron": "^10.1.3", 参考官方文档https://www.electronjs.org/docs/api/app?#apprequestsingleinstancelock
其中例举了代码如下:
const { app } = require('electron') let myWindow = null const gotTheLock = app.requestSingleInstanceLock() if (!gotTheLock) { app.quit() } else { app.on('second-instance', (event, commandLine, workingDirectory) => { // 当运行第二个实例时,将会聚焦到myWindow这个窗口 if (myWindow) { if (myWindow.isMinimized()) myWindow.restore() myWindow.focus() } }) // 创建 myWindow, 加载应用的其余部分, etc... app.on('ready', () => { }) }
按照示例代码,可以很快的完成这一功能项但有一种情况比较特殊,需要修改上面的代码
这种场景就是:如果app被隐藏到托盘中时,一般我们都会设置app不可见:myWindow.hide()
此时app是不可见的状态,所以myWindow.restore()
和myWindow.focus()
是没有用的
解决方法:
在聚焦窗口时先调用myWindow.show()
方法.
最终代码如下:
const { app } = require('electron') let myWindow = null const gotTheLock = app.requestSingleInstanceLock() if (!gotTheLock) { app.quit() } else { app.on('second-instance', (event, commandLine, workingDirectory) => { // 当运行第二个实例时,将会聚焦到myWindow这个窗口 if (myWindow) { mainWindow.show() if (myWindow.isMinimized()) myWindow.restore() myWindow.focus() } }) // 创建 myWindow, 加载应用的其余部分, etc... app.on('ready', () => { }) }
具体代码逻辑(如同我们项目使用的)在app应用创建文件上:
let myWindow = null // 是否单例模式 if (config.IsSingleInstances) { // 此方法的返回值表示你的应用程序实例是否成功取得了锁。 如果它取得锁失败,你可以假设另一个应用实例已经取得了锁并且仍旧在运行,并立即退出。 const gotTheLock = app.requestSingleInstanceLock() // 如果我的应用已经存在,那么就退出当前的进程 if (!gotTheLock) { app.quit() } else { app.on('second-instance', (event, commandLine, workingDirectory) => { // 当运行第二个实例时,将会聚焦到myWindow这个窗口 if (myWindow) { myWindow.show() if (myWindow.isMinimized()) myWindow.restore() myWindow.focus() } }) // 创建 myWindow, 加载应用的其余部分, etc... app.whenReady().then(() => { onAppReady() }) } } else { // 多开模式,每次创建一个进程window会是一个新的, // 第一次打开的进程实例的window对象,如你在上面存储window上面的localStorage,会是你下次创建第一个进程实例的window // 上面的话不好理解?意思就是你第一次创建的进程window上存的值,如果后面再次创建第一个进程, // 那么那个进程的window对象上的值,会是你第一次创建应用的值! // 当Electron 初始化完成。 可用作检查 app.isReady() 的方便选择 // 创建 myWindow, 加载应用的其余部分, etc... app.whenReady().then(() => { onAppReady() }) } // 创建进程窗口 function onAppReady() { // 创建 myWindow, 加载应用的其余部分, etc... myWindow = new initWindow().initWindow() // 根据自己情况去下创建窗口 }
let myWindow = null