Vue.js 中通过 $emit 实现文件上传进度条需子组件用 XMLHttpRequest 监听 upload.onprogress 并节流 emit 进度,父组件 @progress 接收更新 UI;同时处理 cancel、success、error 事件及组件卸载时 abort 防泄漏。

Vue.js 中通过 $emit 实现文件上传进度条的实时反馈,核心在于子组件(如上传控件)主动向父组件传递进度数据,父组件接收后更新 UI。关键不是单纯调用 emit,而是配合原生 XMLHttpRequest 或 fetch + AbortController 的上传事件监听,并确保每次进度变化都及时、节流地触发自定义事件。
子组件中监听 upload 事件并 emit 进度
在封装的上传组件内,使用 XMLHttpRequest 更便于监听上传阶段(upload.onprogress)。避免直接在模板中绑定 input change 后立即上传,应先创建请求实例,再手动配置事件监听:
- 创建
const xhr = new XMLHttpRequest() - 监听
xhr.upload.onprogress = (e) => { if (e.lengthComputable) { const percent = Math.round((e.loaded / e.total) * 100); this.$emit('progress', percent); } } - 注意:必须在
xhr.open()之后、xhr.send()之前绑定upload.onprogress,否则无效 - 为防高频触发,可在 emit 前加简单节流(如
if (Date.now() - lastEmitTime > 100))
父组件监听 progress 事件并驱动进度条
父组件通过 @progress 接收子组件 emit 的数值,绑定到响应式数据,再交给 <progress></progress> 或自定义进度条组件渲染:
- 定义响应式字段:
data() { return { uploadPercent: 0 }; } - 模板中绑定:
<uploadcomponent></uploadcomponent> - 配合 CSS 控制视觉效果,例如设置
transition: width 0.2s ease让进度变化更平滑 - 上传完成或失败时,建议 emit
finish或error事件,重置或锁定进度条状态
处理中断、取消与错误场景
仅反馈进度不够健壮,需同步管理上传生命周期:
立即学习“前端免费学习笔记(深入)”;
- 子组件暴露
cancel方法,内部调用xhr.abort(),并 emitcancelled事件 - 监听
xhr.onloadend判断xhr.status,成功 emitsuccess,失败 emiterror并附带错误信息 - 父组件可据此控制按钮禁用状态(如上传中禁用“再次上传”按钮)、显示提示文案
- 避免内存泄漏:若组件卸载前上传未结束,应在
beforeUnmount中 abort 请求
Vue 3 Composition API 写法适配
若使用 Vue 3,子组件用 defineEmits 显式声明事件,提升类型安全和 IDE 支持:
const emit = defineEmits(['progress', 'success', 'error', 'cancelled'])- emit 调用方式不变:
emit('progress', percent) - 父组件监听语法一致:
@progress="handleProgress",无需额外适配 - 推荐配合
ref管理 xhr 实例,便于在onBeforeUnmount中清理


















