Element|Upload结合Progress实现上传展示进度条

本文介绍了如何在项目中使用Vue的Upload组件结合Progress实现文件上传进度条,包括模拟进度和真实上传时结合http-request和阿里云上传的示例,以及相关事件处理和注意事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背景 :

    项目里的 附件上传 题型组件,用户在上传过程中,如果文件较大,上传过程较慢,而又没有一个类似 Loading... 加载过程的话,会显得干愣愣的,用户体验较差,所以需要添加一个进度条来提示用户上传的进度,下面有两种方式,一种假的,一种真的,伙伴们可根据需求自行选取实现。

    本文章向大家介绍使用 Upload + Progress 实现文件上传进度条实时更新功能,主要包括使用 Upload + Progress 实现文件上传进度条实时更新 功能使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

Upload 上传

通过点击或者拖拽上传文件

Progress 进度条

用于展示操作进度,告知用户当前状态和预期。


“ 简单 && 假 ” 的 进度条 :

利用 setInterval 定时器 模拟实现

<template>
  <div>
    <el-upload
      ref="uploadRef"
      action="#"
      :file-list="fileList"
      :on-change="onChangeData"
      :http-request="handleRequest"
      :before-upload="beforeUpload"
    >
      <el-button v-show="isShowButton" class="btn upload-btn"
        >上传附件</el-button
      >
      <div slot="tip" class="el-upload__tip">上传文件大小不超过50M</div>
    </el-upload>
    <el-progress
      v-show="showProgress"
      :stroke-width="6"
      :percentage="progressPercent"
    ></el-progress>
  </div>
</template>

<script>
import { uploadFileApi } from '@/api';

export default {
  name: 'uploadFile',
  data() {
    return {
      fileType: '', // 文件类型
      fileList: [], // 上传的文件列表
      progressPercent: 0, // 进度条百分比
      isShowButton: false, // 是否显示上传按钮
      showProgress: false, // 是否展示进度条
      isAllowFileTypes: false, // 是否为支持的上传类型
      allowFileTypes: [], // 存储不支持的文件类型
    };
  },
  methods: {
    // 上传的执行方法
    onChangeData(file, fileList) {
      // 前四行代码为了解决:on-change方法第二次调用不起来的问题
      let uploadFilesArr = this.$refs.uploadRef.uploadFiles;
      if (uploadFilesArr.length !== 0) {
        this.$refs.uploadRef.uploadFiles = [];
      }

      let arr = file.name.split('.');
      this.fileType = '.' + arr[arr.length - 1].toLowerCase();
      this.isAllowFileTypes = this.allowFileTypes.includes(this.fileType);
      if (this.isAllowFileTypes) {
        this.isShowButton = false;
        this.fileList = [file];
        if (file.status === 'ready') {
          this.progressPercent = 0;
          this.showProgress = true; // 展示进度条
          const interval = setInterval(() => {
            if (this.progressPercent >= 99) {
              clearInterval(interval);
              return;
            }
            this.progressPercent += 1;
          }, 50);
        }
        if (file.status === 'success') {
          this.progressPercent = 100;
          this.showProgress = false; // 隐藏进度条
        }
      }
    },
    // 文件上传
    async handleRequest(data) {
      let formdata = new FormData();
      formdata.append('file', data.file);
      let res = await uploadFileApi(formdata);
      let { code } = res;
      if (code === '0') {
        // 上传成功
        // ...
      } else if (code === '1') {
        // 上传失败
        this.isShowButton = true;
        this.fileList = [];
      }
    },
    // 上传文件之前的钩子,对文件大小进行校验
    beforeUpload(file) {
      const isLt2M = file.size / 1024 / 1024 < 50;
      if (!isLt2M) {
        this.$message.error('上传文件大小大小不能超过 50MB!');
        return isLt2M;
      }
    },
  },
};
</script>

真实加载的进度条 :

1、使用 Upload + Progress 实现文件上传进度条实时更新功能,需要借助 http-request 属性

具体使用方法如下:

  // 上传的执行方法  
  onChangeData (file, fileList) {
       // 数据小于0.1M的时候按KB显示
      const size = file.size/1024/1024 > 0.1 ? `(${(file.size/1024/1024).toFixed(1)}M)` : `(${(file.size/1024).toFixed(1)}KB)`
      file.name.indexOf('M')>-1 || file.name.indexOf('KB')>-1 ? file.name : file.name += size
  },
  // 文件上传
  handleRequest (data) {
      let formdata = new FormData()
      formdata.append('file', data.file)
      const config = {
        onUploadProgress: progressEvent => {
          // progressEvent.loaded:已上传文件大小
          // progressEvent.total:被上传文件的总大小
          this.progressPercent = Number((progressEvent.loaded / progressEvent.total * 100).toFixed(2))
        }
      }
      this.$axios.post(this.actionURL,formdata,config).then(res => {
        if (res.data.code===1) {}
      })
  },

2、真实进度条,根据文件上传过程中 文件 切片 实现的

<template>
  <div class="uploadBtn">
    <el-upload
      ref="uploadRefs"
      class="upload-demo"
      action=""
      accept="mp4"
      :limit="1"
      :file-list="fileListA"
      :http-request="UploadFileA"
      :on-change="handleChange"
      :on-success="handleSuccess"
    >
      <el-button size="small" type="primary">点击上传</el-button>
    </el-upload>
    <el-progress v-if="uploading" :percentage="uploadPercentage"></el-progress>
  </div>
</template>

<script>
export default {
  name: 'Upload',
  data() {
    return {
      fileListA: [], // 上传的文件列表
      uploading: false, // 是否正在上传
      uploadPercentage: 0, // 进度条百分比
    };
  },
  methods: {
    //上传图片到阿里云
    UploadFileA(file) {
      console.time('executionTime'); //测试文件上传所耗时间开始
      const baseUrl = 'https://你的阿里云地址aliyunUrl.com';
      const fileName = file.file.uid + file.file.name; //文件信息
      const url = baseUrl + '/resource/你的阿里云文件夹地址/' + fileName; //拼接地址
      const xhr = new XMLHttpRequest();
      xhr.upload.addEventListener('progress', (event) => {
        if (event.lengthComputable) {
          const percentage = Math.round((event.loaded * 100) / event.total);
          this.uploadPercentage = percentage; // 给进度条赋值
        }
      });
      xhr.onreadystatechange = () => {
        if (xhr.readyState === XMLHttpRequest.DONE) {
          if (xhr.status === 200 || xhr.status === 201) {
            console.log('阿里云文件', xhr);
            this.formData.fileUrl = xhr.responseURL;
            this.uploadPercentage = 100; // 上传完成后显示100%进度
            console.timeEnd('executionTime'); //测试文件上传所耗时间结束,打印时间为所耗时间,为毫秒级
          } else {
            console.error('上传失败');
          }
          this.uploading = false; // 设置上传状态为 false,隐藏进度条
        }
      };
      this.uploading = true; // 设置上传状态为 true,显示进度条
      this.uploadPercentage = 0; // 设置进度条初始值为0%
      xhr.open('PUT', url, true);
      xhr.send(file.file);
    },
  },
};
</script>

相关参数解答:

    xhr.onreadystatechange 是 XMLHttpRequest 对象的一个事件处理程序,

它在请求状态发生变化时触发。XMLHttpRequest 对象用于与服务器进行异步通信,onreadystatechange 事件在接收到服务器响应并且请求状态发生变化时被触发。
    具体来说,xhr.onreadystatechange 事件在以下几种情况下被触发:
        xhr.readyState 的值发生变化时
        xhr.status 的值发生变化时
        xhr.statusText 的值发生变化时
        xhr.response 的值发生变化时
    xhr.readyState 是 XMLHttpRequest 对象的属性,表示请求的状态。

    它有如下几个可能的值:
        0:未初始化。XMLHttpRequest 对象已创建或已被 abort() 方法重置。
        1:打开。open() 方法已被调用,但 send() 方法未被调用。
        2:发送。send() 方法已被调用,并且头部和状态已经可获得。
        3:接收。正在接收服务器的响应数据。
        4:完成。已经接收到全部响应数据,并且可以在客户端使用了。


    在 xhr.onreadystatechange 事件处理程序中,我们通常使用条件判断来确定请求的状态是否满足特定条件,以执行相应的操作。例如,在上面的代码中,我们检查 xhr.readyState 是否等于 XMLHttpRequest.DONE,来确定 请求是否已完成

  如果是,则进一步检查 xhr.status 是否为 200 或 201,来确定请求是否成功。
通过使用 xhr.onreadystatechange 事件处理程序,我们可以根据不同的请求状态来执行相应的逻辑,例如更新页面内容、处理错误等。

    xhr.upload 是 XMLHttpRequest 对象的一个属性,而不是事件处理程序。
    xhr.upload 属性是用于处理上传过程中的事件的。

  它是一个包含了与上传相关事件的 XMLHttpRequestUpload 对象。
        在前面提到的代码中,我们使用了 xhr.upload.addEventListener 方法来注册一个 progress 事件监听器。这个事件监听器用于追踪上传的进度

`el-upload` 是 Element UI 提供的一个用于文件上传的功能组件。要在上传框中添加加载效果,你可以使用 Vue.js 的响应式状态以及一些 CSS 动画或者过渡效果。这里是一个简单的例子: 1. 首先,在模板上添加一个显示/隐藏上传按钮或加载动画的元素,例如一个 `div`,并绑定一个 `v-loading` 属性: ```html <template> <el-upload ref="upload" :action="uploadUrl" :show-file-list="false" :on-change="handleChange" :before-upload="beforeUpload" v-loading="uploadLoading" > <!-- 这里可以添加一个点击按钮 --> <el-button @click="submitFile" :disabled="uploadLoading">选择文件</el-button> <!-- 或者直接使用 <input type="file"> 并设置 @change="handleChange" --> </el-upload> <div v-if="uploadLoading" class="loading-indicator">正在上传...</div> </template> ``` 2. 在数据对象中定义 `uploadLoading` 值和相关的事件处理函数: ```js <script> export default { data() { return { uploadUrl: '你的上传接口地址', uploadLoading: false, // 表示是否加载中 submitFile() { this.uploadLoading = true; // 开始加载时设为 true this.$refs.upload.submit(); // 发起上传请求 }, handleChange(file) { // 上传完成后,将 uploadLoading 设回 false this.uploadLoading = false; }, beforeUpload(file) { // 在上传开始前检查一些条件,如文件类型、大小等 // 如果需要取消上传,返回 false // ... return true; }, }; }, }; </script> ``` 3. 对于动画效果,你可以在 CSS 中设置 `.loading-indicator` 类的样式,比如使用 `vue-loading-spinner` 库或者自定义 CSS 3 过渡效果。 ```css .loading-indicator { display: flex; justify-content: center; align-items: center; height: 100%; /* 添加一个动画 */ animation: spin 1s linear infinite; } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } ```
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值