在 Electron 中卸载前确认
Confirm beforeunload in Electron
我知道有数百个问题,例如:"How can i prevent close event in electron" 或类似的问题。
在 beforeunload
事件中实现确认框(电子消息框)后,我能够关闭我的应用程序并取消关闭事件。由于开发工具始终处于打开状态,我没有意识到在关闭开发工具时它不起作用...
window.onbeforeunload = e =>
{
// show a message box with "save", "don't save", and "cancel" button
let warning = remote.dialog.showMessageBox(...)
switch(warning)
{
case 0:
console.log("save");
return;
case 1:
console.log("don't save");
return;
case 2:
console.log("cancel");
return false;
// e.returnValue = "false";
// e.returnValue = false;
}
};
所以,当打开开发工具时,我可以关闭应用程序并保存,不保存并取消事件。
关闭开发工具后,取消按钮将不再起作用。
顺便说一句:
window.onbeforeunload = e =>
{
return false;
alert("foo");
};
将取消关闭事件并且显然不会显示消息(无论开发工具是打开还是关闭都无所谓)
window.onbeforeunload = e =>
{
alert("foo");
return false;
};
如果开发工具已打开,将在按确定后取消关闭事件;如果开发工具已关闭,将在按确定后关闭应用程序
我有意使用消息框的同步 api,在写这个问题时我发现一个双窗口应用程序 (new remote.BrowserWindow()
) 的行为与开发工具。
有人知道我该如何解决这个问题吗?
非常感谢
而不是 onbeforeunload
更喜欢使用事件 close
。从此事件中,您将能够在整个关闭过程完成之前捕获关闭事件(事件 closed
)。使用 close
,您将能够控制并在需要完成关闭时停止。
这在您创建 BrowserWindow 时是可能的,最好是在主进程中:
// Create the browser window.
window = new BrowserWindow({});
// Event 'close'
window.on('close', (e) => {
// Do your control here
if (bToStop) {
e.preventDefault();
}
})
// Event 'closed'
window.on('closed', (e) => {
// Fired only if you didn't called e.preventDefault(); above!
})
此外,请注意函数 e.preventDefault()
正在整个代码中传播。如果你需要回到 Electron 的自然行为,你需要将变量 e.defaultPrevented
切换为 false
.
实际上,e.preventDefault()
函数似乎正在处理变量 e.defaultPrevented
到 true
,直到它发生任何变化。
更新:
正如我在上面接受的答案的评论中提到的,preventDefault
在 Windows 上被忽略了。准确地说,我将它放在用户关闭应用程序时打开的本机电子对话框的回调中。
因此我采用了不同的方法:
let close: boolean = false
win.on('close', (ev: any) => {
if (close === false) {
ev.preventDefault()
dialog.showMessageBox({
type: 'warning',
buttons: ['Cancel', 'Ok'],
title: 'Do not forget to safe your changes',
cancelId: 0,
defaultId: 1,
noLink: true
}).then((val) => {
if (val.response === 0) {
// Cancel the close process
} else if (win) {
close = true
app.quit()
}
})
}
})
也许这会帮助有类似需求的人,我有一个包含在电子应用程序中的反应应用程序,反应应用程序与电子无关,也可以 运行 在浏览器中和我的要求本来是要显示默认的浏览器提示,臭名昭著的 Leave Site?
警报。
在浏览器中这很容易,例如我只是这样做:
useEffect(() => {
window.onbeforeunload = promptOnProjectLeave ? () => true : undefined;
return () => {
window.onbeforeunload = undefined;
}
}, [promptOnProjectLeave]);
这将显示默认浏览器 Leave Site?
提示,但在电子中,这只会阻止 window 在没有任何操作提示询问您是否确定的情况下关闭,所以我的方法是这个 post 和另一个 .
的混合
这就是解决方案
mainWindow.webContents.on('will-prevent-unload', (event) => {
const options = {
type: 'question',
buttons: ['Cancel', 'Leave'],
message: 'Leave Site?',
detail: 'Changes that you made may not be saved.',
};
const response = dialog.showMessageBoxSync(null, options)
if (response === 1) event.preventDefault();
});
这将允许我在我的反应代码中使用 window.onbeforeunload
就像在浏览器中一样,在浏览器中我将获得默认的浏览器提示,在电子中我将获得一个消息框 :)
这是我第一次使用 Electron,因此可能有一些改进方法,但无论哪种方式,希望这对某人有所帮助,我知道当我开始这项任务时它会对我有所帮助。
您可以简单地使用 'pagehide'
事件。它似乎适用于电子应用程序。它的工作方式与 'beforeunload'
略有不同,因为它不能阻止关闭 window/tab,但是如果您只需要在页面关闭之前做一些事情(使用 navigator.sendBeacon()
发送一些异步请求等)那么这个活动可能会满足您的需求。
您可以阅读更多相关信息here, here and in the docs
用法示例:
window.addEventListener('pagehide', () => {
window.navigator.sendBeacon(url, data);
}
我知道有数百个问题,例如:"How can i prevent close event in electron" 或类似的问题。
在 beforeunload
事件中实现确认框(电子消息框)后,我能够关闭我的应用程序并取消关闭事件。由于开发工具始终处于打开状态,我没有意识到在关闭开发工具时它不起作用...
window.onbeforeunload = e =>
{
// show a message box with "save", "don't save", and "cancel" button
let warning = remote.dialog.showMessageBox(...)
switch(warning)
{
case 0:
console.log("save");
return;
case 1:
console.log("don't save");
return;
case 2:
console.log("cancel");
return false;
// e.returnValue = "false";
// e.returnValue = false;
}
};
所以,当打开开发工具时,我可以关闭应用程序并保存,不保存并取消事件。
关闭开发工具后,取消按钮将不再起作用。
顺便说一句:
window.onbeforeunload = e =>
{
return false;
alert("foo");
};
将取消关闭事件并且显然不会显示消息(无论开发工具是打开还是关闭都无所谓)
window.onbeforeunload = e =>
{
alert("foo");
return false;
};
如果开发工具已打开,将在按确定后取消关闭事件;如果开发工具已关闭,将在按确定后关闭应用程序
我有意使用消息框的同步 api,在写这个问题时我发现一个双窗口应用程序 (new remote.BrowserWindow()
) 的行为与开发工具。
有人知道我该如何解决这个问题吗?
非常感谢
而不是 onbeforeunload
更喜欢使用事件 close
。从此事件中,您将能够在整个关闭过程完成之前捕获关闭事件(事件 closed
)。使用 close
,您将能够控制并在需要完成关闭时停止。
这在您创建 BrowserWindow 时是可能的,最好是在主进程中:
// Create the browser window.
window = new BrowserWindow({});
// Event 'close'
window.on('close', (e) => {
// Do your control here
if (bToStop) {
e.preventDefault();
}
})
// Event 'closed'
window.on('closed', (e) => {
// Fired only if you didn't called e.preventDefault(); above!
})
此外,请注意函数 e.preventDefault()
正在整个代码中传播。如果你需要回到 Electron 的自然行为,你需要将变量 e.defaultPrevented
切换为 false
.
实际上,e.preventDefault()
函数似乎正在处理变量 e.defaultPrevented
到 true
,直到它发生任何变化。
更新:
正如我在上面接受的答案的评论中提到的,preventDefault
在 Windows 上被忽略了。准确地说,我将它放在用户关闭应用程序时打开的本机电子对话框的回调中。
因此我采用了不同的方法:
let close: boolean = false
win.on('close', (ev: any) => {
if (close === false) {
ev.preventDefault()
dialog.showMessageBox({
type: 'warning',
buttons: ['Cancel', 'Ok'],
title: 'Do not forget to safe your changes',
cancelId: 0,
defaultId: 1,
noLink: true
}).then((val) => {
if (val.response === 0) {
// Cancel the close process
} else if (win) {
close = true
app.quit()
}
})
}
})
也许这会帮助有类似需求的人,我有一个包含在电子应用程序中的反应应用程序,反应应用程序与电子无关,也可以 运行 在浏览器中和我的要求本来是要显示默认的浏览器提示,臭名昭著的 Leave Site?
警报。
在浏览器中这很容易,例如我只是这样做:
useEffect(() => {
window.onbeforeunload = promptOnProjectLeave ? () => true : undefined;
return () => {
window.onbeforeunload = undefined;
}
}, [promptOnProjectLeave]);
这将显示默认浏览器 Leave Site?
提示,但在电子中,这只会阻止 window 在没有任何操作提示询问您是否确定的情况下关闭,所以我的方法是这个 post 和另一个
这就是解决方案
mainWindow.webContents.on('will-prevent-unload', (event) => {
const options = {
type: 'question',
buttons: ['Cancel', 'Leave'],
message: 'Leave Site?',
detail: 'Changes that you made may not be saved.',
};
const response = dialog.showMessageBoxSync(null, options)
if (response === 1) event.preventDefault();
});
这将允许我在我的反应代码中使用 window.onbeforeunload
就像在浏览器中一样,在浏览器中我将获得默认的浏览器提示,在电子中我将获得一个消息框 :)
这是我第一次使用 Electron,因此可能有一些改进方法,但无论哪种方式,希望这对某人有所帮助,我知道当我开始这项任务时它会对我有所帮助。
您可以简单地使用 'pagehide'
事件。它似乎适用于电子应用程序。它的工作方式与 'beforeunload'
略有不同,因为它不能阻止关闭 window/tab,但是如果您只需要在页面关闭之前做一些事情(使用 navigator.sendBeacon()
发送一些异步请求等)那么这个活动可能会满足您的需求。
您可以阅读更多相关信息here, here and in the docs
用法示例:
window.addEventListener('pagehide', () => {
window.navigator.sendBeacon(url, data);
}