el-Upload 总结(源码)

  element 是非常常用的 UI 组件库。最近,因为公司需求的变化,需要让上传的文件有个上传的进度条。刚开始,还不知道怎么去做,后来想到了 element 中的 upload 组件。就做个总结(包含一定的源码):

  之前我总结过一篇关于upload 的钩子自定义传参的总结

upload组件的参数及事件(部分)

  • action:上传地址

  • headers:上传的请求头

  • multiple:是否支持上传多个文件

  • data:上传时附带的额外的参数

  • on-success:上传成功时的钩子

  • on-error:上传失败时的钩子

  • on-change:文件状态改变时的钩子

  • on-progress:文件上传时的钩子

  最后一个 on-progress 钩子是实现上传进度的关键。该钩子能够返回请求上传(发送)的进度(%)。

  1. 第一个参数:event,包含了上传进度等

  2. 第二个参数:file,当前上传的文件信息等

  3. 第三个参数: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。

posted @ 2022-05-02 16:37  攻城Alone  阅读(871)  评论(0编辑  收藏  举报