在 JavaScript 中捕获弹出窗口的关闭事件

我需要在弹出窗口(使用 window.open)关闭之前执行一些操作。

比如说“将会是好的”:

var new_window = window.open('some url')
new_window.onBeforeUnload = function(){ my code}

我怎么才能做到呢?

160612 次浏览

You need to bind the onbeforeunload event to the window AFTER it is opened.

The simplest way to do that would be to have the javascript onbeforeunload code within the window source code.

For detailed explanations, refer to these two very similar questions here and here on Stackoverflow.

The event name is onbeforeunload and not onBeforeUnload. JS is case sensitive.

Your example will work as long as the pop-up window url is in the same domain as the parent page, and you change the event to all lowercase:

var new_window = window.open('some url')
new_window.onbeforeunload = function(){ /* my code */ }

As stated above, you need to bind the onbeforeunload event to the window after it is opened.

See example in other thread: https://stackoverflow.com/a/25989253/578275.

var new_window = window.open('some_url')

You can also check if new_window.window is null. But you need to manually check it with setTimeout or setInterval functions.

This is btw the only way how to check it when you are not on the same domain.

While the accepted answer is correct for same origins I found a solution for cross origin popups:

var win = window.open('http://www.google.com');
var timer = setInterval(function() {
if(win.closed) {
clearInterval(timer);
alert('closed');
}
}, 1000);

Source: atashbahar.com

For those considering using it.

Even Facebook is using this "hack" in their Javascript SDK.

You can verify this by having a look at their code. Just search for .closed in https://connect.facebook.net/en_US/sdk.js.

onbeforeunload event must be added after loading of pop-up window. For example, you can add it at the end of its load event like below;

const new_window = window.open('some url')
new_window.onload = function(){
/* my code */
this.onbeforeunload = function(){ /* my code */ }
}

You probably do not want to overwrite the value of onbeforeunload, because this will interfere with the popout's handler if it also uses that hook.

Use addEventListener('beforeunload', ...) instead.

const wnd = window.open(theUrl)
wnd.addEventListener('beforeunload', () => {
// do stuff
})

Please note, other options exists for events, such as unload and pageHide. Read docs to see what event is best for your implementation.

For reference:

https://developer.mozilla.org/en-US/docs/Web/API/Window/beforeunload_event

https://developer.mozilla.org/en-US/docs/Web/API/Window/unload_event

https://developer.mozilla.org/en-US/docs/Web/API/Window/pagehide_event

For an overview of the page lifecycle, see:

https://developers.google.com/web/updates/2018/07/page-lifecycle-api#developer-recommendations-for-each-state

import { useEffect, useRef } from "react";


const usePopupWindow = ({
url,
onPopupClose,
popupProperties = "width=200,height=200",
}) => {
const timer = useRef();


const handleWindowPopup = () => {
const windowPopup = window.open(url, "popup", popupProperties);


timer.current = setInterval(() => {
if (windowPopup.closed) {
clearInterval(timer.current);
onPopupClose();
}
}, 1000);
};


useEffect(() => {
return () => clearInterval(timer.current);
}, []);


return { handleWindowPopup };
};


export default usePopupWindow;

Created this hook for React use case