Vanilla JS中Window Unload异常:需标签关闭后执行函数
Hey there! I get why those initial approaches aren't working for you—modern browsers have strict restrictions on what you can do in beforeunload and unload events to prevent annoying pop-ups and ensure smooth page transitions. Let's fix this step by step.
Why Your Previous Methods Failed
onunload/onbeforeunloadwithalert(): Browsers block synchronous dialogs (likealert,confirm) in these events now—they don't want sites spamming users as they try to leave. That's why you saw the "Blocked alert..." error.- Running
bye()inbeforeunload: Thebeforeunloadevent fires before the user chooses to stay or leave. So yourbye()runs immediately when the user clicks the tab's close button, not after they confirm "Leave"—which is exactly the issue you're facing.
The Working Approach
To run code only after the user confirms they want to leave, you need to combine two events:
- Use
beforeunloadto show the browser's native confirmation dialog (this is allowed, since it's the browser's own prompt, not a custom one). - Use the
unloadevent to execute your function—this event fires after the user has confirmed leaving, right as the page is unloading.
Important note: You can't use interactive functions like alert() or confirm() in unload—browsers will block them. Stick to non-interactive tasks like sending analytics data, cleaning up resources, etc. For reliable data sending, use navigator.sendBeacon() (it's designed specifically for this scenario, as it ensures the request completes even after the page unloads).
Here's the code:
// Step 1: Trigger the native leave confirmation dialog window.addEventListener('beforeunload', (event) => { // Required to show the native dialog (browser-specific) event.preventDefault(); event.returnValue = ''; // Empty string works for most browsers }); // Step 2: Run your function ONLY after user confirms leaving window.addEventListener('unload', () => { bye(); }); function bye() { console.log('User confirmed leaving—executing cleanup/action!'); // Example: Send data with sendBeacon (recommended for async tasks) if (navigator.sendBeacon) { const data = new FormData(); data.append('action', 'user_left'); navigator.sendBeacon('/your-endpoint', data); } }
For Vue.js Users (Even Though You Asked for Vanilla JS)
Since you mentioned using Vue, here's how you'd implement this in a component (still using vanilla JS under the hood):
<template> <!-- Your component content --> </template> <script> export default { mounted() { // Add event listeners when component mounts window.addEventListener('beforeunload', this.handleBeforeUnload); window.addEventListener('unload', this.handleUnload); }, beforeUnmount() { // Clean up event listeners when component unmounts window.removeEventListener('beforeunload', this.handleBeforeUnload); window.removeEventListener('unload', this.handleUnload); }, methods: { handleBeforeUnload(event) { event.preventDefault(); event.returnValue = ''; }, handleUnload() { this.bye(); }, bye() { console.log('User left the page!'); // Add your logic here } } } </script>
Key Limitations to Keep in Mind
- The
unloadevent is not 100% reliable in all edge cases (e.g., if the browser crashes). - You can't delay the page unload or run long-running tasks here—keep your
bye()function lightweight. navigator.sendBeacononly supports POST requests and doesn't allow custom headers in some browsers, so adjust your backend accordingly if you're using it.
内容的提问来源于stack exchange,提问作者Mohammad Basit

