文件上传进度条为什么卡在0%不动?

司空美美 阅读 128

我在做文件上传功能时加了进度条,用XMLHttpRequest监听progress事件,但上传开始后进度条一直显示0%没变化,这是为什么?

我用CSS写了简单的进度条样式:


.progress-container {
  width: 100%;
  height: 20px;
  background: #eee;
  border-radius: 10px;
}
.progress-bar {
  height: 100%;
  background: #4CAF50;
  width: 0%;
  transition: width 0.1s;
}

JS部分这样写的:
const xhr = new XMLHttpRequest();
xhr.upload.addEventListener(‘progress’, (e) => {
if(e.lengthComputable) {
const percent = (e.loaded / e.total)*100;
console.log(percent); // 这里能正常输出进度
document.querySelector(‘.progress-bar’).style.width = ${percent}%;
}
});
但页面上的进度条完全没变化,控制台也没报错…

我来解答 赞 5 收藏
二维码
手机扫码查看
2 条解答
Good“艺涵
我之前也碰到过这问题,其实不是进度条没动,而是你的 元素可能根本没被选中,或者 DOM 更新被浏览器批量合并了。

先确认几个关键点:

第一,检查下你是不是在 progress 回调里直接改了 width,但 .progress-bar 元素是动态生成的,或者还没插入 DOM。比如你用 querySelector('.progress-bar'),但页面上其实没有这个 class,或者它还没渲染出来。

第二,也是最容易被忽略的一点:你写的是 width: ${percent}%;,但模板字符串用的是反引号吗?你代码里写的是 ...style.width = ${percent}%; —— 这里如果没用反引号包裹,percent 就是字符串拼接错误,实际设置的是 "${percent}%" 这个字面量字符串,浏览器根本不会解析成数字。我第一次写的时候就栽这儿了,以为是 JS 的问题,结果是模板字符串没用反引号。

正确的写法应该是:

document.querySelector('.progress-bar').style.width = ${percent}%;


或者最稳妥的写法(避免 DOM 问题):

const bar = document.querySelector('.progress-bar');
if (bar) {
bar.style.width = ${percent}%;
}


第三,如果前面都对,但进度条还是不动,可能是浏览器做了重绘优化,你可以强制触发一下重排,比如加一行:

bar.offsetHeight; // 触发重排


不过一般加上模板字符串反引号就解决了,我之前就是手快漏了反引号,调试了半小时……你先试试这个,应该就 OK 了。
点赞 8
2026-02-26 21:34
Mc.金利
Mc.金利 Lv1
问题出在你设置进度条宽度的方式上,具体来说是字符串拼接的问题。你在设置 style.width 时用了模板字符串,但没加引号,导致生成的样式值不合法。

正确的写法应该是这样:
document.querySelector('.progress-bar').style.width = ${percent}%;


这里的关键是,CSS 的 width 属性需要一个带单位的字符串值,比如 "50%"。你原来的写法会生成一个不带引号的值,浏览器无法正确解析。

另外提醒几点安全和兼容性方面的注意事项:
上传大文件时,记得处理超时和网络中断的情况,最好加个错误处理的监听器。还有,现在的前端开发建议用更现代的 fetch API 配合 AbortController 来实现上传功能,虽然 XMLHttpRequest 还能用,但已经有点过时了。

最后吐槽一句,这种因为少了引号导致的 bug 真的是调试起来最让人抓狂的,我以前也被坑过好几次。
点赞 9
2026-02-14 02:02