用 $emit 实现文件上传进度条刷新,核心是子组件在 onUploadProgress 中计算百分比并持续触发 'upload-progress' 事件,父组件监听后更新响应式 percent 变量驱动 Progress 组件重绘,需处理初始化、完成、失败、取消及多文件等边界情况。

用 $emit 实现文件上传进度条刷新,核心是子组件在上传过程中分段触发事件,把当前进度值传给父组件,父组件接收后更新 percent 数据驱动视图重绘。这不是一次性通知,而是持续、高频的“进度广播”。
子组件:监听上传过程并 emit 进度
上传逻辑通常在子组件内封装(比如调用 axios 或原生 fetch),关键是在请求的 onUploadProgress 回调中计算百分比,并通过 $emit 发出:
- 获取文件总大小(
event.total)和已上传字节数(event.loaded) - 算出整数型百分比:
Math.round((event.loaded / event.total) * 100) - 用固定事件名(如
'upload-progress')发出进度值:this.$emit('upload-progress', percent) - 注意:需在上传开始前初始化进度为 0,上传完成或失败时 emit 100 或错误状态,避免进度卡住
父组件:监听事件并响应更新
父组件在使用子组件时,绑定自定义事件,并在处理函数中直接赋值给响应式数据:
- 模板中写:
<file-uploader @upload-progress="onProgress" /> - 方法中写:
onProgress(val) { this.percent = val } -
percent必须是 data 或 ref 定义的响应式变量,才能触发 Progress 组件重绘 - 可加防抖或节流(如每 50ms 最多更新一次),避免高频 emit 导致渲染压力
配合 UI:Progress 组件绑定 percent
进度条显示依赖实时数据,确保模板中正确绑定:
- 使用 Ant Design Vue 的 Progress:
<Progress :percent="percent" /> - Vue 3 + Composition API 可用 ref:
<Progress :percent="percent" />,其中const percent = ref(0) - 若需多文件各自进度,建议 emit 时携带文件标识(如
{ id: 'file1', percent: 65 }),父组件用对象或 Map 存储各文件状态
边界情况处理建议
真实场景中容易忽略但影响体验的点:
- 上传取消时,应 emit 0 并清空当前任务,避免残留进度
- 网络中断或报错,emit 一个特殊值(如 -1)或额外事件(
@upload-error),让父组件切换状态提示 - 多个文件并发上传时,父组件不宜简单取平均值;推荐展示“第 n 个文件:xx%”,或汇总已完成数/总数
- 移动端要注意 emit 频率,部分机型对高频事件响应迟钝,可降为每 200ms 更新一次

















