如何在完全动态加载的页面中监听类似document.readyState的事件?
动态加载页面资源加载完成监听方案
document.readyState仅对应整页初始加载的状态,动态插入DOM后的资源加载不会触发该状态更新,也不会触发全局readystatechange事件,因此需要手动统计插入内容的资源加载情况,以下是两种可落地的实现方案:
方案1:预加载资源后再插入DOM(体验最优)
该方案会先预加载所有需要用到的资源,全部加载完成后再把页面内容插入到DOM中,用户不会看到资源逐步加载的闪烁过程,完全符合你的需求。
实现步骤
- 拿到AJAX返回的页面HTML后,先通过临时DOM节点提取所有资源地址,包括图片的src、srcset,视频的src、封面图,资源地址需要去重避免重复加载
- 逐个创建资源实例预加载,统计总资源数和已加载完成(含加载失败)的数量
- 所有资源加载完成后,再插入页面内容、隐藏加载屏,同地址资源浏览器会直接读取缓存,不会重复发起请求
示例代码
$.ajax({ url: '你的子页面接口地址', type: 'GET', beforeSend: function() { // 显示加载屏 $('.loading-screen').show(); }, success: function(res) { // res中pageContent为页面HTML,otherData为你需要的额外业务数据 const { pageContent, otherData } = res; // 临时DOM用于提取资源 const tempDom = document.createElement('div'); tempDom.innerHTML = pageContent; // 收集所有需要预加载的资源 const resources = []; // 收集图片资源 tempDom.querySelectorAll('img').forEach(img => { img.src && resources.push(img.src); img.srcset && resources.push(...img.srcset.split(',').map(item => item.trim().split(' ')[0])); }); // 收集视频相关资源 tempDom.querySelectorAll('video').forEach(video => { video.src && resources.push(video.src); video.poster && resources.push(video.poster); }); tempDom.querySelectorAll('video source').forEach(source => { source.src && resources.push(source.src); }); // 资源去重 const uniqueResources = [...new Set(resources)]; let loadedCount = 0; const totalCount = uniqueResources.length; // 兜底:没有资源直接完成 if (totalCount === 0) { insertPageContent(pageContent); return; } // 超时兜底:避免资源加载失败导致加载屏永远显示 const loadTimeout = setTimeout(() => { insertPageContent(pageContent); }, 3000); // 可自行调整最长等待时间 // 逐个预加载资源 uniqueResources.forEach(url => { const isImage = /\.(png|jpg|jpeg|gif|webp|svg)$/i.test(url); const isVideo = /\.(mp4|webm|ogg)$/i.test(url); let loadElement; if (isImage) { loadElement = new Image(); } else if (isVideo) { loadElement = document.createElement('video'); loadElement.preload = 'auto'; } else { // 其他类型资源用fetch预加载 fetch(url).then(handleLoad, handleLoad); return; } loadElement.onload = handleLoad; loadElement.onerror = handleLoad; // 加载失败也计数,不阻塞流程 loadElement.src = url; }); function handleLoad() { loadedCount++; if (loadedCount === totalCount) { clearTimeout(loadTimeout); insertPageContent(pageContent); } } function insertPageContent(content) { // 插入页面内容 $('#page-container').html(content); // 隐藏加载屏 $('.loading-screen').hide(); // 执行history.push、其他业务逻辑 // ... } } });
方案2:先插入DOM再监听资源加载
如果你的页面资源体积过大,不想让用户长时间等待白屏,可以先把页面内容插入DOM,再监听容器内所有资源的加载事件,加载完成后再隐藏加载屏,实现逻辑和方案1基本一致,仅调整插入DOM的时机即可。
可选优化
可以通过loadedCount / totalCount计算加载进度,在加载屏上展示进度百分比,进一步提升用户体验。
内容的提问来源于stack exchange,提问作者thelaumix
相关产品推荐
相关产品推荐

