JavaScript如何实现进度条_前端进度如何模拟
发布时间 - 2026-01-02 00:00:00 点击率:次用 setInterval 模拟进度条最直接,需控制数字从 0 增至 100 并绑定 DOM;requestAnimationFrame 更流畅但需时间戳计算;XMLHttpRequest 支持 onprogress 获取真实进度;AbortController 中断时须同步清理定时器或动画帧。
用 setInterval 模拟进度条最直接
没有真实后端接口时,前端常靠定时器“假装”加载中。核心是控制一个数字从 0 逐步增加到 100,再绑定到 DOM 元素的宽度或文本上。
关键点:别用 setTimeout 递归调用(易失控),setInterval 更可控;记得在达到 100 后 clearInterval,否则内存泄漏。
- 初始值设为
0,步长建议1~5,太小卡顿,太大不平滑 - 间隔时间选
50~200ms,100ms是较自然的节奏 - 避免在循环里频繁操作 DOM,先更新数据,再统一渲染
let progress = 0;
const timer = setInterval(() => {
progress += 2;
document.querySelector('.progress-bar').style.width = `${progress}%`;
if (progress >= 100) {
clearInterval(timer);
}
}, 100);用 requestAnimationFrame 实现更流畅的动画
当对视觉平滑度有要求(比如上传大文件预览进度),requestAnimationFrame 比 setInterval 更合适——它会自动对齐屏幕刷新率,且页面切到后台时暂停,省资源。
但注意:它不保证固定时间间隔,只保证“下一帧”,所以不能直接当计时器用,需配合时间戳计算进度比例。
- 记录开始时间
startTime = performance.now() - 每次回调中算出已过毫秒数,除以总耗时得到
0~1的完成比 - 仍需手动判断是否结束并停止递归调用
const startTime = performance.now(); const duration = 3000; // 总时长 3s
function animateProgress() { const elapsed = performance.now() - startTime; const progress = Math.min(100, (elapsed / duration) * 100); document.querySelector('.progress-bar').style.width =
${progress}%; if (progress < 100) { requestAnimationFrame(animateProgress); } } requestAnimationFrame(animateProgress);
真实请求中如何把 XMLHttpRequest 的 onprogress 接出来
只有原生 XMLHttpRequest 支持上传/下载进度事件,fetch 目前不支持(虽有提案,但未落地)。如果你用的是 axios,它底层封装了 XMLHttpRequest,可通过 onUploadProgress 或 onDownloadProgress 钩子拿到。
重点:必须设置 Content-Length(服务端要返回 Content-Length 响应头),否则 event.total 为 0,无法算百分比。
-
event.loaded是已传输字节数,event.total是总字节数 - 上传时用
xhr.upload.onprogress,下载时用xhr.onprogress - 某些 CDN 或代理可能过滤掉
Content-Length,导致total === 0,此时只能显示“正在处理…”而非精确百分比
const xhr = new XMLHttpRequest();
xhr.open('POST', '/upload');
xhr.upload.onprogress = (event) => {
if (event.lengthComputable) {
const percent = (event.loaded / event.total) * 100;
document.querySelector('.progress-bar').style.width = `${Math.round(percent)}%`;
}
};
xhr.send(file);用 AbortController 中断进度条逻辑
用户点了“取消”按钮后,不仅要终止请求,还要让进度条停在当前值或归零——否则会出现“请求已停,但进度条还在跑”的错觉。
常见误区:只调 abort(),却没清理定时器或动画帧。必须把所有异步控制句柄(intervalId、animationFrameId、controller)统一管理。
- 把
setInterval的返回值存到变量,abort时一起clearInterval - 用
requestAnimationFrame时,保存上次返回的 id,并在 abort 时用cancelAnimationFrame - 不要在
finally或catch里盲目重置进度为 0,得区分是成功结束、失败中断还是用户取消
进度条最难的不是怎么画,而是状态同步:请求、UI、用户操作三者之间稍有脱节,就会出现跳变、卡死或假完成。尤其在移动端弱网下,loaded 可能长时间不更新,这时候加个超时 fallback 比强行“动起来”更重要。
# javascript
# java
# 前端
# 字节
# axios
# 后端
# ios
# cdn
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
PHP怎么接收前端传的文件路径_处理文件路径参数接收方法【汇总】
Laravel怎么使用Intervention Image库处理图片上传和缩放
Laravel怎么实现软删除SoftDeletes_Laravel模型回收站功能与数据恢复【步骤】
悟空浏览器如何设置小说背景色_悟空浏览器背景色设置【方法】
Laravel如何使用Eloquent ORM进行数据库操作?(CRUD示例)
Laravel怎么实现支付功能_Laravel集成支付宝微信支付
如何用免费手机建站系统零基础打造专业网站?
如何使用 Go 正则表达式精准提取括号内首个纯字母标识符(忽略数字与嵌套)
微信小程序 require机制详解及实例代码
Windows10电脑怎么查看硬盘通电时间_Win10使用工具检测磁盘健康
利用python获取某年中每个月的第一天和最后一天
Laravel如何使用Blade组件和插槽?(Component代码示例)
Windows Hello人脸识别突然无法使用
bootstrap日历插件datetimepicker使用方法
专业型网站制作公司有哪些,我设计专业的,谁给推荐几个设计师兼职类的网站?
详解阿里云nginx服务器多站点的配置
如何在阿里云部署织梦网站?
WEB开发之注册页面验证码倒计时代码的实现
linux top下的 minerd 木马清除方法
为什么php本地部署后css不生效_静态资源加载失败修复技巧【技巧】
昵图网官方站入口 昵图网素材图库官网入口
如何用PHP工具快速搭建高效网站?
Laravel怎么使用artisan命令缓存配置和视图
1688铺货到淘宝怎么操作 1688一键铺货到自己店铺详细步骤
Laravel如何优雅地处理服务层_在Laravel中使用Service层和Repository层
如何在阿里云服务器自主搭建网站?
Laravel中的withCount方法怎么高效统计关联模型数量
jquery插件bootstrapValidator表单验证详解
长沙做网站要多少钱,长沙国安网络怎么样?
韩国代理服务器如何选?解析IP设置技巧与跨境访问优化指南
php在windows下怎么调试_phpwindows环境调试操作说明【操作】
Angular 表单中正确绑定输入值以确保提交与验证正常工作
极客网站有哪些,DoNews、36氪、爱范儿、虎嗅、雷锋网、极客公园这些互联网媒体网站有什么差异?
html文件怎么打开证书错误_https协议的html打开提示不安全【指南】
JavaScript如何实现路由_前端路由原理是什么
免费制作统计图的网站有哪些,如何看待现如今年轻人买房难的情况?
Laravel如何编写单元测试和功能测试?(PHPUnit示例)
Laravel如何从数据库删除数据_Laravel destroy和delete方法区别
国美网站制作流程,国美电器蒸汽鍋怎么用官方网站?
Win11搜索不到蓝牙耳机怎么办 Win11蓝牙驱动更新修复【详解】
Laravel表单请求验证类怎么用_Laravel Form Request分离验证逻辑教程
在线制作视频网站免费,都有哪些好的动漫网站?
北京网站制作公司哪家好一点,北京租房网站有哪些?
UC浏览器如何切换小说阅读源_UC浏览器阅读源切换【方法】
如何快速建站并高效导出源代码?
用yum安装MySQLdb模块的步骤方法
如何快速上传建站程序避免常见错误?
做企业网站制作流程,企业网站制作基本流程有哪些?
微信小程序 input输入框控件详解及实例(多种示例)
高性价比服务器租赁——企业级配置与24小时运维服务


st startTime = performance.now();
const duration = 3000; // 总时长 3s