【前端学习记录】vue中使用el-upload组件时,上传文件进度条没有实时更新

文章讲述了在使用el-upload组件进行文件上传时遇到的进度条不实时更新的问题。通过分析问题背景和原理,提出通过监听on-progress事件并使用this.$forceUpdate()强制更新DOM的解决方案。同时提醒注意强制更新的副作用,并提供了相关Vue组件渲染的知识。

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

问题背景

今天在项目中遇到一个问题,使用el-upload组件时,上传文件进度条没有实时更新,需要手动点击一下才会更新。

原理及可尝试方案

el-upload 组件默认的进度条是通过 Ajax 请求上传文件,并且进度条通过监听 xhr.upload 的 progress 事件来实时更新。但是,有些浏览器在处理进度事件时可能会存在问题,导致进度条不会实时更新。

如果进度条没有实时更新,可以尝试使用 el-upload 组件提供的 on-progress 事件来手动更新进度条。具体做法是在 on-progress 事件处理函数中,将上传进度值赋给进度条的 percentage 属性。如下所示:

<el-upload
  action="/upload"
  :on-progress="handleUploadProgress"
>
  <el-button slot="trigger" size="small" type="primary">点击上传</el-button>
</el-upload>
methods: {
  handleUploadProgress(event, file, fileList) {
    // 计算上传进度
    const progress = Math.ceil((event.loaded / event.total) * 100);
    // 将进度赋给进度条的 percentage 属性
    file.percentage = progress;
    // 如果不使用 file.percentage 属性,而是使用 fileList 的方式更新进度条,请参考下面的代码
    // const index = fileList.findIndex(item => item.uid === file.uid);
    // fileList[index].percentage = progress;

    // 强制更新 DOM
    this.$forceUpdate();
  }
}

在 handleUploadProgress 方法中,计算上传进度并将进度赋给 file.percentage 属性。然后,使用 this.$forceUpdate() 强制更新 DOM,使进度条实时更新。

这种方法可以解决进度条不实时更新的问题,但要注意的是,在每次更新进度条时,可能会导致组件重新渲染,因此如果列表中有其他需要保留的状态,要注意在更新前先保存这些状态,以免丢失。

查文档

<el-upload
  class="upload-demo"
  action="https://jsonplaceholder.typicode.com/posts/"
  :on-progress="handleProgress"
  :on-preview="handlePreview"
  :on-remove="handleRemove"
  :before-remove="beforeRemove"
  multiple
  :limit="3"
  :on-exceed="handleExceed"
  :file-list="fileList">
  <el-button size="small" type="primary">点击上传</el-button>
  <div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过500kb</div>
</el-upload>

on-progress 为文件上传时的钩子,回调函数为 function(event, file, fileList),经过测试,在代码上传时,会定时触发该方法,在event中会定时更新返回的进度,但是页面上没有发生变化,判断问题的原因是dom没有更新。

最终,在handleProgress中增加this.$forceUpdate();问题解决。

this.$forceUpdate();

this.$forceUpdate() 是 Vue 实例的一个方法,用于强制刷新组件的 DOM。它会导致组件重新渲染,即使没有进行数据的改变。

在 Vue 中,组件的渲染是响应式的,当数据发生变化时,Vue 会自动更新组件的 DOM。但有时候,我们希望手动触发组件的重新渲染,即使数据没有改变。这时就可以使用 this.$forceUpdate() 方法。

this.$forceUpdate() 方法会使组件的 render 函数重新执行,生成新的 VNode,并对比新旧 VNode 的差异来更新 DOM。它会跳过组件实例的依赖追踪,直接强制刷新整个组件。

注意1: this.$forceUpdate() 方法在应用程序中一般不常用。在大多数情况下,Vue 会自动追踪响应式数据的变化并更新组件,不需要手动调用 this.$forceUpdate()。只有在某些特殊情况下,例如当组件的渲染依赖于非响应式数据或外部事件时,才需要使用它。

注意2:this.$forceUpdate() 只会触发当前组件的重新渲染,而不会影响其父组件或子组件的重新渲染。如果需要更新父组件或子组件的 DOM,应该使用相应的机制,如父子组件之间通过 prop 和事件交互。

总结一下,this.$forceUpdate() 方法是 Vue 实例上的一个方法,用于强制刷新组件的 DOM,即使数据没有改变。但一般情况下,不建议频繁使用该方法,而是依赖 Vue 的自动响应式机制来更新组件的 DOM。

Element Plus 的 `eel-upload` 组件支持批量上传文件,当你需要检查所有文件是否已全部上传完毕,可以结合使用 `file-list` 和 `on-change` 或 `on-progress` 事件监听器。 首先,你需要获取到所有上传文件的信息,通常会在 `file-list` 中看到每个文件的状态。你可以设置一个变量来记录正在上传文件总数,以及一个数组来存储每个文件的唯一标识符和其对应的进度。 例如: ```html <template> <div> <el-upload ref="upload" :action="uploadUrl" :multiple="true" :file-list="fileList" @change="handleFileChange" @progress="checkUploadProgress" ></el-upload> <!-- 显示上传状态信息 --> <ul v-if="!allFilesUploaded"> <li v-for="(file, index) in fileList" :key="index"> {{ file.name }} - {{ file.percent || '等待上传' }} <span class="status" :class="{ uploading: file.status === 'uploading', done: file.status === 'done' }"></span> </li> </ul> </div> </template> <script setup> import { ref } from 'vue'; const uploadUrl = 'your-upload-url'; let allFilesUploaded = ref(false); let uploadedFiles = []; function handleFileChange(fileList) { // 更新fileList fileList.forEach((file) => { uploadedFiles.push(file); if (!file.status || file.status !== 'done') { allFilesUploaded.value = false; } }); } function checkUploadProgress(progressEvent) { const file = progressEvent.file; if (file && file.status === 'uploading') { // 更新单个文件的进度 const index = uploadedFiles.findIndex(f => f.uid === file.uid); if (index > -1) { uploadedFiles[index].percent = progressEvent.percentage; } // 检查是否所有文件都已上传 allFilesUploaded.value = uploadedFiles.every(file => file.status === 'done'); } } </script> ``` 当 `allFilesUploaded` 变为 `true` ,说明所有的文件都已经上传完成。记得在实际应用中处理上传成功、失败及中断的情况。同,确保在 `@change` 事件触发后初始化 `uploadedFiles` 数组,以便后续跟踪每个文件上传状态。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值