element 是非常常用的 UI 组件库。最近,因为公司需求的变化,需要让上传的文件有个上传的进度条。刚开始,还不知道怎么去做,后来想到了 element 中的 upload 组件。就做个总结(包含一定的源码):
之前我总结过一篇关于upload
的钩子自定义传参的总结
upload组件的参数及事件(部分)
-
action:上传地址
-
headers:上传的请求头
-
multiple:是否支持上传多个文件
-
data:上传时附带的额外的参数
-
on-success:上传成功时的钩子
-
on-error:上传失败时的钩子
-
on-change:文件状态改变时的钩子
-
on-progress:文件上传时的钩子
最后一个 on-progress
钩子是实现上传进度的关键。该钩子能够返回请求上传(发送)的进度(%)。
-
第一个参数:event,包含了上传进度等
-
第二个参数:file,当前上传的文件信息等
-
第三个参数:fileList,上传的文件列表
相关功能实现的原理
完成需求后,觉得很nice。同时有点想看下是怎么实现这个功能的,就看了下源码。
- 上传进度 (ajax.js 文件中)
export default function upload(option) { if (typeof XMLHttpRequest === 'undefined') { return; } const xhr = new XMLHttpRequest(); const action = option.action; if (xhr.upload) { xhr.upload.onprogress = function progress(e) { if (e.total > 0) { e.percent = e.loaded / e.total * 100; } option.onProgress(e); }; } .... .... }
- 取消上传
// 上传的 file 对象 abort(file) { this.$refs['upload-inner'].abort(file); },
还记得上面几张图中都有个uid吗,没看源码之前,我还以为这个有可能一样或者变化的不是随着上传的文件而变化,还特意试下。后来发现是我有点多虑了。
watch: {
fileList: {
immediate: true,
handler(fileList) {
this.uploadFiles = fileList.map(item => {
item.uid = item.uid || (Date.now() + this.tempIndex++);
item.status = item.status || 'success';
return item;
});
}
}
}
这个监听一开始就会执行,如果没有uid,就使用当前时间戳 + tempIndex,给列表中每个对象添加 uid。
handleStart(rawFile) {
rawFile.uid = Date.now() + this.tempIndex++;
let file = {
status: 'ready',
name: rawFile.name,
size: rawFile.size,
percentage: 0,
uid: rawFile.uid,
raw: rawFile
};
....
....
},
这个方法(methods中),会给每个上传的文件对象里添加 uid。