el-upload 多文件依次上传(防抖 + 递归)

news2024/11/26 13:51:21

需求描述

  • 多图上传组件,1-9 张图
  • 选择完文件后自动上传,不需要上传按钮来进行手动上传

难点

  • 接口有两种,多图集合上传接口 uploadImgs、单图上传接口 uploadImg
    • 使用 uploadImgs 接口,参数为图片集合 fileList,但是缺少上传按钮,无法监听用户选择完图片的时间点
    • 使用 uploadImg 接口,参数为图片 file,接口被多次同时调用造成服务器压力

解决思路

  • 关闭 auto-upload 属性,手动控制上传进程,监听组件的 change 事件
  • 使用防抖函数,监听 change 事件
  • 选择多张图片后,组件每读取到一张图片就会调用一次 change 事件
  • change 事件被触发后的某时间段内如果没有再次被触发,视为用户此次选择图片结束
  • 获取待上传的文件列表,将图片集合传递给后台
  • 如果调用单图上传,需要加入递归,重复多次调用上传接口,将待上传文件列表中的内容逐一上传
<el-upload
  action=""
  list-type="picture-card"
  multiple
  show-file-list
  :on-change="changeFile"
  :on-exceed="exceedFile"
  :auto-upload="false"
  :file-list="fileList"
  :limit="9"
  :disabled="disabled"
  ref="upload"
>
  <i class="el-icon-plus"></i>
</el-upload>
data() {
  return {
    timmer: null, // 用于控制防抖的定时器
    fileList: [], // 文件列表--上传结束后回显用
    disabled: false, // 控制组件是否禁用
    uploadFileList: [], // 上传文件列表--待传递
    successFileUrls: [], // 记录上传成功的文件列表--用不到,这里为了方便演示
  };
},
// 防抖函数
debounce(func, delay) {
  return (() => {
    if (this.timmer) {
      // 如果已经存在,说明之前执行过了,这里要清除,重新开始
      console.log("%c清理定时器的操作~", "color: blue;");
      clearTimeout(this.timmer);
    }
    this.timmer = setTimeout(func, delay);
  })();
},
changeFile(file, fileList) {
  console.log("触发组件change事件", file, fileList);
  // 开启禁用开关
  this.disabled = true;
  this.debounce(() => {
    this.uploadFileList = JSON.parse(JSON.stringify(fileList)); // 文件列表赋值
    // this.uploadImg(); // 执行上传事件--单图上传
    this.uploadImgs(); // 执行上传事件--多图上传
    this.timmer = null;
  }, 1000);
},
exceedFile() {
  this.$message.error("上传文件最多9个");
},
// 上传事件--多图上传
uploadImgs() {
  console.log("%c模拟接口执行上传事件----开始上传", "color: red;");
  console.log(this.uploadFileList);
  if (this.uploadFileList.length > 0) {
    this.mockFunc(2, this.uploadFileList)
      .then((res) => {
        console.log("%c模拟接口执行上传事件----成功", "color: green;");
        this.successFileUrls.push(res);
        console.log("当前已上传成功的文件", this.successFileUrls);
        // 实际应用接口,返回文件 url 集合,用 url 集合结果覆盖掉 fileList
        // fileList 被返回结果覆盖掉之后,也会同时清理掉组件中上传失败的文件
        // this.fileList = this.successFileUrls;
      })
      .catch(() => {
        console.log(
          "%c模拟接口执行上传事件----失败",
          "color: yellowgreen;"
        );
      });
  }
},
// 上传事件--单图上传
uploadImg() {
  console.log("%c模拟接口执行上传事件----开始上传", "color: red;");
  console.log(this.uploadFileList);
  if (this.uploadFileList.length > 0) {
    this.mockFunc(1, this.uploadFileList[0])
      .then((res) => {
        console.log("%c模拟接口执行上传事件----成功", "color: green;");
        this.successFileUrls.push(res);
        console.log("当前已上传成功的文件", this.successFileUrls);
        // 实际应用接口,返回文件 url 集合,用 url 集合结果覆盖掉 fileList
        // this.fileList = this.successFileUrls;
        this.uploadFileList.shift(); // 上传成功后,删除待传递列表的第一个
        this.uploadImg(); // 递归,执行下一个操作
      })
      .catch(() => {
        console.log(
          "%c模拟接口执行上传事件----失败",
          "color: yellowgreen;"
        );
      });
  } else {
    console.log("待上传文件列表全部传递完毕");
    // 关闭禁用开关
    this.disabled = false;
  }
},
 // 模拟接口--手动延时、返回正确或错误结果
mockFunc(type, file) {
  if (type == 1) {
    // 模拟单图上传
    return new Promise((resolve, reject) => {
      console.log("上传的文件为", file.name);
      let params = new FormData();
      params.append("file", file);
      console.log("file", file);
      setTimeout(() => {
        let radio = file.size / 1024 / 1024;
        if (radio <= 2) {
          // 接口得到图片云存储的路径 url,这里用 name 代替
          resolve(file.name);
        } else {
          reject();
        }
      }, 200);
    });
  } else {
    // 模拟多图上传
    return new Promise((resolve, reject) => {
      let params = new FormData();
      let fileName = []; // 模拟接口返回值,实际用不到
      file.forEach((item) => {
        let radio = item.size / 1024 / 1024;
        if (radio <= 2) {
          params.append("file", item);
          // 接口得到图片云存储的路径 url,这里用 name 代替
          fileName.push(item.name);
        }
      });
      console.log("file", file);
      setTimeout(() => {
        resolve(fileName);
      }, 200);
    });
  }
},

结果演示

  • 未调用实际接口,在 mockFunc 中记录文件名称,来模拟后台接口响应中返回的文件云存储路径。
  • 调用接口结束后,使用接口响应中返回的云存储路径覆盖掉 fileList,使上传组件回显的图片集合,与上传成功后的图片集合保持一致

调用 uploadImgs 多图上传

  • 选择三张小于 2M 的图片上传
  • change 事件被触发 3 次,在第 3 次结束后,1000ms 内,未被再次触发,开始调用上传接口
  • 上传接口调用成功,返回结果

在这里插入图片描述

  • 选择两张小于 2M 的图片,一张大于 2M 的图片上传
  • change 事件被触发 3 次,每触发一次,向待上传数组 uploadFileList 中塞一个 file 对象,在第 3 次结束后,1000ms 内,未被再次触发,开始调用上传接口,将 uploadFileList 传递给后台
  • 上传接口调用成功,返回结果,结果集合的长度为 2,表示上传图片列表中有一张上传失败了,在实际接口应用中,使用接口响应结果覆盖掉 el-upload 绑定的 fileList 即可

在这里插入图片描述

调用 uploadImg 单图上传

  • 选择三张小于 2M 的图片上传
  • change 事件被触发 3 次,每触发一次,向待上传数组 uploadFileList 中塞一个 file 对象,在第 3 次结束后,1000ms 内,未被再次触发,开始递归调用上传接口
  • 假设 uploadFileList = [img1,img2,img3] ,此时 uploadFileList 长度为 3,表示当前有 3 张图片待上传,调用接口,传递 uploadFileList[0] 对象,即 img1,调用结束后,将 uploadFileList 第一项删除,此时 uploadFileList = [img2,img3]
  • 继续调用上传接口,此时 uploadFileList 长度为 2,表示当前有两张图片待上传,调用接口,传递 uploadFileList[0] 对象,即 img2,调用结束后,将 uploadFileList 第一项删除,此时 uploadFileList = [img3]
  • 继续调用上传接口,此时 uploadFileList 长度为 1,表示当前有 1 张图片待上传,调用接口,传递 uploadFileList[0] 对象,即 img3,调用结束后,将 uploadFileList 第一项删除,此时 uploadFileList = []
  • 继续嗲用上传接口,此时 uploadFileList 长度为 0,表示待上传图片已经全部上传完毕,结束上传进程

在这里插入图片描述

  • 选择两张小于 2M 的图片,一张大于 2M 的图片上传
  • 递归流程同上
  • 上传接口调用成功,返回结果,结果集合的长度为 2,表示上传图片列表中有一张上传失败了,在实际接口应用中,使用接口响应结果覆盖掉 el-upload 绑定的 fileList 即可

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/627428.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Spring架构篇--2.7.4 远程通信基础--Netty原理--bind实现客户端acceptread事件处理

前言&#xff1a;本文在Netty 服务端已经实现NioServerSocketChannel 管道的初始化并且绑定了端口后&#xff0c;继续对客户端accept&read事件如何处理进行探究&#xff1b; 1 对客户端accept&read事件的触发&#xff1a; 从之前的ServerBootstrap 的bind 方法中似乎…

JMeter接口测试新思路——灵活使用BeanShell

目录 前言&#xff1a; BeanShell的简介 调用Java方法 执行Class文件 结合实际案例 总结 前言&#xff1a; 在JMeter进行接口测试时&#xff0c;我们可能会遇到需要调用Java方法或者执行Java代码的情况&#xff0c;这时候我们可以使用BeanShell来实现。BeanShell是一个类…

QuintoAndar 如何提高转化率

QuintoAndar 如何提高转化率 ——求关注、求点赞、求分享&#xff0c;二毛拜谢。 QuintoAndar 如何通过提高页面性能来提高每次会话的转化率和页面数 一个专注于优化 Core Web Vitals 并迁移到 Next.js 的项目使转换率提高了 5%&#xff0c;每个会话的页面增加了 87%。 Quint…

07.JavaWeb-Vue+elementUI

1.Vue 功能替代JavaScript和jQuery&#xff0c;基于JavaScript实现的前端框架 1.1配置Vue 1.1.1引入vue库 方法一&#xff1a;通过cdn链接引入最新版本的vue&#xff08;可能会慢些&#xff09; <head><script src"https://cdn.jsdelivr.net/npm/vue">…

基于yolov5开发构建道路路面病害检测识别系统——以捷克、印度、日本三国城市道路实况场景数据为例,开发对比分析模型并分析对应性能

城市道路病害检测是最近比较热门的一个任务领域&#xff0c;核心就是迁移深度学习目前已有的研究成果来实现实时城市道路路面病害的检测识别分析&#xff0c;在我之前的很多博文中都有做过类似桥梁、大坝、基建、隧道等水泥设施裂缝裂痕等目标检测相关的项目&#xff0c;除此之…

利用powershell脚本进行内网渗透

powershell知识点 ps1是powershell脚本的拓展名&#xff0c;就相当于cmd的.bat脚本&#xff0c;但是他更加强大。 获取版本信息 get-host #查看powershell的版本信息$psversiontable #查看powershell的版本信息执行策略 PowerShell 执行策略是一项安全功能&#xff0c;用于控…

softmax之温度系数

1.数学表示 这是传统的softmax&#xff1a; q i e x p ( z i ) ∑ j e x p ( z j ) q_i \frac{exp(z_i)}{\sum_jexp(z_j)} qi​∑j​exp(zj​)exp(zi​)​ 或者写&#xff1a; q i e x p ( z i ) / 1.0 ∑ j e x p ( z j / 1.0 ) q_i \frac{exp(z_i)/1.0}{\sum_jexp(z_j/…

《LCHub低代码指南》:ChatGPT会取代低代码开发平台吗?

目录 一、低代码开发平台的优势 1. 提高开发效率 2. 降低开发成本 3. 提高应用程序的质量 二、ChatGPT的优势 三、ChatGPT是否会取代低代码开发平台 四、结论 随着数字化时代的到来,低代码开发平台已经成为了企业数字化转型的重要工具之一。然而,随着人工智能技术的不…

提升教学质量,监督教室课堂秩序?这招小白也能轻松搞定

在当今快速发展的教育领域&#xff0c;提高教学质量和监督教师的工作表现是学校和教育机构的重要任务之一。 传统的巡课方式存在许多限制&#xff0c;如耗时、人力成本高以及数据收集和分析的困难等。为了应对这些挑战&#xff0c;越来越多的学校和教育机构转向在线巡课系统&am…

微信小程序怎么直播?

我们目前使用的小程序都是支持直播功能的&#xff0c;小程序直播功能是通过小程序直播组件实现的&#xff0c;这是微信为商家提供的实时视频直播工具&#xff0c;可以帮助商家快速通过小程序向用户提供优质的直播内容。同时&#xff0c;借助小程序丰富的营销功能&#xff0c;使…

一、Drools 规则引擎

一、问题引出 现有一个在线申请信用卡的业务场景&#xff0c;用户需要录入个人信息&#xff0c;如下图所示&#xff1a; 通过上图可以看到&#xff0c;用户录入的个人信息包括 姓名、性别、年龄、学历、电话、所在公司、职位、月收入、是否有房、是否有车、是否有信用卡等。录入…

Netty中ServerBootstrap类介绍

一、Netty基本介绍 Netty是由JBOSS提供的一个java开源框架。Netty提供异步的、事件驱动的网络应用程序框架和工具&#xff0c;用以快速开发高性能、高可靠性的网络服务器和客户端程序。Netty 在保证易于开发的同时还保证了其应用的性能&#xff0c;稳定性和伸缩性。 Netty 是一…

UE5 PCG模块学习1

这次来学习一下UE5.2中正式加入的PCG功能。网上较多的案例是在Landscape地形上创建贴合地面的物体&#xff0c;博主研究了一下&#xff0c;这个案例将创建贴合Mesh的物体&#xff1a; 1.基础生成 1.首先在插件中检查Procedural Content Generation Framework是否已经被开启&…

自学黑客的12个步骤

黑客攻防是一个极具魅力的技术领域&#xff0c;但成为一名黑客毫无疑问也并不容易。你必须拥有对新技术的好奇心和积极的学习态度&#xff0c;具备很深的计算机系统、编程语言和操作系统知识&#xff0c;并乐意不断地去学习和进步。 如果你想成为一名优秀的黑客&#xff0c;下…

Java 获取七牛云存储空间中的所有图片列表

文章目录 获取七牛云密钥导入依赖编辑 YAML 配置文件添加七牛云配置类编写 QiNiuImgUrls 方法测试结果 七牛云官方文档&#xff1a;https://developer.qiniu.com/kodo/sdk/java 如果有还不会使用SpringBoot整合七牛云存储的小伙伴们&#xff0c;可以跳转查看这篇文章&#xff1…

Revit中如何画弯曲的轴网和显示实时轴号?

一、Revit中如何画弯曲的轴网 生活中&#xff0c;有很多圆筒样式的建筑&#xff0c;比如说鸟巢和土楼&#xff0c;他们的外壁是弯曲的。所以&#xff0c;当我们用Revit创建这类模型时&#xff0c;轴网就要画弯曲的&#xff0c;那么&#xff0c;Revit中如何画弯曲的轴网呢&#…

JMeter接口压测和性能监测

引言 今天我来和大家分享一篇关于JMeter接口压测和性能监测的文章。在现代互联网时代&#xff0c;应用程序的性能已经成为了一个非常重要的问题&#xff0c;并且对于许多公司的生存和发展都起着至关重要的作用。 而在这其中&#xff0c;JMeter是一个非常实用的工具&#xff0…

CSAPP - AttackLab实验(阶段1-5)

AttackLab实验 实验内容 官网&#xff1a;http://csapp.cs.cmu.edu/3e/labs.html “AttackLab”是一个Linux下的可执行C程序&#xff0c;包含了5个阶段&#xff08;phase1~phase5&#xff09;的不同内容。程序运行过程中&#xff0c;要求学生能够根据缓冲区的工作方式和程序…

【Flutter】如何移除 Flutter 右上角的 DEBUG 标识

文章目录 一、前言二、什么是 DEBUG 标识三、为什么我们需要移除 DEBUG 标识四、如何移除 DEBUG 标识五、完整代码六、总结 一、前言 欢迎来到 Flutter 的世界&#xff01;在这篇文章中&#xff0c;我们将探索 Flutter 的一些基础知识。但是&#xff0c;你知道吗&#xff1f;这…

Science:“消除噪音”量子比特实现了纠错的重大突破

光子盒研究院 在《科学》杂志的一篇新论文中&#xff0c;芝加哥大学普利兹克分子工程学院Hannes Bernien助教实验室的研究人员描述了一种不断监测量子系统周围噪音并实时调整量子比特以减少误差的方法——他们引入了“旁观者量子比特(spectator qubit)”。 尽管他们有解决新型问…