You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何正确制作页面preloader 实现等待页面完全加载后自动消失

Preloader 实现思路与技巧

以下是几种可以精准监听页面加载状态、无需固定定时器的实现方案:

方案1:原生加载事件 + 请求计数器组合

这个方案适合所有类型的站点,兼容性最好:

  • 先监听window.load事件,该事件会等待页面所有关联静态资源(图片、字体、样式、同步脚本)加载完成后才触发,注意不要仅依赖DOMContentLoaded事件,后者仅在DOM解析完成时触发,不会等静态资源和异步请求。
  • 给所有初始数据请求增加计数逻辑:定义全局变量pendingRequests等于初始请求的总数量,每个请求完成(无论成功失败)时将计数减1。
  • 当window.load触发且pendingRequests计数归0时,再隐藏preloader。

简单实现示例:

let pendingRequests = 3; // 替换为你实际的初始请求数量
let isPageStaticLoaded = false;

// 每个初始请求结束时调用该方法
function finishRequest() {
  pendingRequests--;
  tryHidePreloader();
}

// 监听静态资源加载完成
window.addEventListener('load', () => {
  isPageStaticLoaded = true;
  tryHidePreloader();
});

function tryHidePreloader() {
  if (pendingRequests === 0 && isPageStaticLoaded) {
    document.querySelector('.preloader').style.display = 'none';
  }
}

如果使用Axios等请求库,可以直接在响应拦截器里统一处理计数逻辑,不用手动给每个请求加回调。

方案2:Promise 统一管理所有初始任务

适合单页应用、所有初始加载逻辑可控的场景:

  • 把所有需要等待的任务(初始接口请求、首屏特殊资源预加载、自定义初始化逻辑)全部封装为Promise,放到同一个数组中。
  • 使用Promise.allSettled监听所有任务完成,就算某个请求失败也不会导致preloader永远不消失。

简单实现示例:

// 整合所有初始加载任务
const initLoadTasks = [
  fetch('/api/init-config'),
  fetch('/api/user-info'),
  // 可加入自定义资源加载任务,比如首屏大图
  new Promise((resolve) => {
    const heroImage = document.querySelector('.hero img');
    heroImage.complete ? resolve() : heroImage.onload = resolve;
  })
];

// 所有任务完成后隐藏加载器
Promise.allSettled(initLoadTasks).then(() => {
  document.querySelector('.preloader').classList.add('preloader--hide');
});

通用优化技巧

  • 增加最小显示时长:避免页面加载速度太快导致preloader闪一下就消失,体验割裂,可以设置至少300ms的最小显示时间,计算preloader已显示时长,不足就用setTimeout延迟隐藏。
  • 增加最长兜底时长:设置10s左右的最长显示时间,就算有请求卡住也会自动隐藏preloader,避免用户永远无法访问页面。
  • 可搭配进度提示:如果初始任务数量固定,可以根据已完成任务数计算加载进度,给用户更明确的反馈。

内容的提问来源于stack exchange,提问作者mmm42

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.20 11:36:05