如何阻止浏览器后退时onbeforeunload事件触发加载模态框弹出?
问题根因
- 你注册的定时器属于页面全局上下文,当页面被推入浏览器**往返缓存(Back/Forward Cache,简称bfcache)**时(用户点击后退就会触发该缓存逻辑,页面不会真的销毁),之前设置的2秒定时器并不会被自动清除,页面从缓存恢复后定时器到期就会执行
showLoader弹出模态框。 - 原逻辑没有判断导航来源,后退恢复的页面会直接执行加载框显示逻辑。
修改后完整代码
// 全局存储定时器ID,方便后续清除 let unloadTimer = null; window.onbeforeunload = function () { unloadTimer = window.setTimeout(showLoader, 2000); } // 监听pageshow事件,页面从缓存恢复时触发 window.addEventListener('pageshow', function(e) { // 页面从bfcache恢复时,清除定时器+销毁可能存在的模态框 if (e.persisted) { if (unloadTimer) { clearTimeout(unloadTimer); unloadTimer = null; } const loadModal = document.getElementById('layoutLoadingModal'); if (loadModal) loadModal.remove(); } }); // 监听pagehide事件,页面即将被缓存/销毁时先清除定时器 window.addEventListener('pagehide', function() { if (unloadTimer) { clearTimeout(unloadTimer); unloadTimer = null; } }); function showLoader() { // 增加导航类型判断,后退/前进场景下不弹出加载框 const navEntry = performance.getEntriesByType('navigation')[0]; if (navEntry && navEntry.type === 'back_forward') return; var loader = '<div id="layoutLoadingModal" class="modal fade" role="dialog">' + '<div class="modal-dialog">' + '<div class="modal-content">' + '<div class="modal-body">' + '<h1>Loading!</h1>' + '</div>' + '</div>' + '</div>' + '</div>'; $("body").append(loader); $('#layoutLoadingModal').modal('show'); }
核心改动说明
- 全局存储定时器ID,在
pagehide(页面即将被缓存/销毁)和pageshow(页面从缓存恢复)两个节点清除定时器,从根源避免缓存页面的定时器到期触发逻辑。 - 利用Performance API判断当前导航类型,如果是后退/前进触发的页面加载,直接跳过加载框的显示逻辑。
- 页面从bfcache恢复时自动检测并移除已存在的加载模态框,避免残留。
内容的提问来源于stack exchange,提问作者Fredrik Kindahl
相关产品推荐
相关产品推荐

