ASP.NET Core MVC中jQuery beforeunload在iOS上加载屏失效问题
iOS Safari 刷新页面加载屏不显示的修复方案
针对iOS Safari刷新时加载屏无法正常显示的问题,核心原因是iOS的页面卸载机制对DOM渲染的限制,以及原有事件监听和判断逻辑的适配性不足。以下是具体修复步骤和代码:
关键修复点
- 强制同步渲染加载屏:iOS Safari在页面卸载时会节流DOM操作,必须强制浏览器立即完成渲染,避免加载屏被跳过。
- 优化链接触发判断逻辑:仅依赖
document.activeElement在iOS部分场景下不准确,改为从事件源向上遍历判断是否为链接。 - 区分pagehide事件的缓存状态:利用
event.persisted判断是否为后退/前进缓存(bfcache)场景,避免误触发加载屏。
修改后的完整代码
function isEventTriggeredByLink(event) { // 从事件目标向上遍历,优先判断是否为链接 let target = event.target; while (target && target.tagName !== 'BODY') { if (target.tagName === 'A') { return true; } target = target.parentNode; } // 回退到activeElement判断,兼容其他场景 const activeElement = document.activeElement; return activeElement && activeElement.tagName === 'A'; } function showLoadingScreen() { let loader = document.getElementById('loading-screen'); if (!loader) { // 创建加载屏元素(可根据需求修改样式) loader = document.createElement('div'); loader.id = 'loading-screen'; loader.style.cssText = ` position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: #ffffff; display: flex; align-items: center; justify-content: center; z-index: 9999; font-size: 16px; `; loader.textContent = '加载中...'; document.body.appendChild(loader); } else { loader.style.display = 'flex'; } // 强制浏览器同步渲染,解决iOS刷新时不显示的核心问题 void loader.offsetHeight; } function hideLoadingScreen() { const loader = document.getElementById('loading-screen'); if (loader) { loader.style.display = 'none'; } } // 处理页面卸载(包含刷新) $(window).on('beforeunload', function (event) { if (!isEventTriggeredByLink(event)) { showLoadingScreen(); // 辅助触发浏览器渲染,不阻止刷新操作 event.preventDefault(); } }); // 处理iOS pagehide事件,区分bfcache场景 $(window).on('pagehide', function (event) { // persisted为false时是刷新/直接关闭,需要显示加载屏 if (!event.persisted && !isEventTriggeredByLink(event)) { showLoadingScreen(); } }); // 处理页面可见性变化 document.addEventListener('visibilitychange', function (event) { if (document.visibilityState === 'hidden') { if (!isEventTriggeredByLink(event)) { showLoadingScreen(); } } else if (document.visibilityState === 'visible') { hideLoadingScreen(); } }); // 页面加载完成后隐藏加载屏 $(window).on('load', function () { hideLoadingScreen(); }); // 从bfcache恢复页面时隐藏加载屏 $(window).on('pageshow', function (event) { if (event.persisted) { hideLoadingScreen(); } });
额外说明
- iOS Safari刷新时,页面卸载流程极快,所有加载屏的DOM操作必须同步执行,禁止使用setTimeout等异步方法,否则会被浏览器忽略。
- 如果你的加载屏是通过CSS类控制显示/隐藏,同样需要在切换类后执行
void element.offsetHeight;强制重排。
内容的提问来源于stack exchange,提问作者Vështrim Mulaku
相关产品推荐
相关产品推荐

