iview中基于upload源代码组件封装更为完善的上传组件

业务背景

  • 最近接了一个用iview为基础搭建的vue项目,在开需求研讨会议的时候,我个人提了一个柑橘很合理且很常规的建议,upload上传文件支持同时上传多个并且可限制数量。当时想的是这不应该很正常吗,但是尴尬的是:只有multiple 开启选项,并无limit属性。

初始解决问题的思路

  1. 通过业务代码来控制
    • 但是尴尬的是,搞了三个小时硬是没有成功解决这个问题
  2. 引入第三方插件
    • 这个感觉是最简单的方案了,但是这好像不是我的风格,为了一个小功能点去引入一个插件。
    • 直接放弃
  3. 修改源代码
    • 这是当发现我通过业务代码无法解决问题后的常规想法

如何修改源代码呢

  • 幸好,在不久的半年前我手撸过element uiupload源代码,二者结合一下吧,让iview适当抄袭下element ui

element ui 源代码里的 upload 组件限制上传数量代码如何实现的呢?

  1. 在props里定义了limit接收字段,

  2. 在input type="file"的 on-change 事件里调用的 uploadFiles 方法中做好 数量限制的逻辑判断

uploadFiles 整体函数代码

js 复制代码
 uploadFiles(files) {
      if (this.limit && this.fileList.length + files.length > this.limit) {
        this.onExceed && this.onExceed(files, this.fileList);
        return;
      }

      let postFiles = Array.prototype.slice.call(files);
      if (!this.multiple) { postFiles = postFiles.slice(0, 1); }

      if (postFiles.length === 0) { return; }

      postFiles.forEach(rawFile => {
        this.onStart(rawFile);
        if (this.autoUpload) this.upload(rawFile);
      });
    },

核心代码

js 复制代码
if (this.limit && this.fileList.length + files.length > this.limit) {
    this.onExceed && this.onExceed(files, this.fileList);
    return;
}

具体逻辑

  • 当前文件列表的长度 + 这次上传的文件长度 > 总计限制的数量
  • 即抛出异常,并拦截

iview 如何实现的呢?并且有什么问题呢

  1. 压根就没有传入limt限制最大上传数量字段
  2. 没有传入数量超出异常回调函数
  3. uploadFiles 方法并没有 进行
    • 当前文件列表的长度 + 这次上传的文件长度 > 总计限制的数量,- 即抛出异常,并拦截 的逻辑处理
  4. 没有将次此上传的多个文件列表抛出到调用的业务组件,故无法通过业务层拦截
    • 而是将文件列表循环一个个依次抛出
    • 直接导致了iview 内部的 upload件底层没有做最大数量的拦截、同时也无法通过业务层代码进行拦截,

核心代码

js 复制代码
handleChange (e) {
    const files = e.target.files;

    if (!files) {
        return;
    }
    this.uploadFiles(files);
    this.$refs.input.value = null;
},
uploadFiles (files) {
    let postFiles = Array.prototype.slice.call(files);
    if (!this.multiple) postFiles = postFiles.slice(0, 1);

    if (postFiles.length === 0) return;

    postFiles.forEach(file => {
        this.upload(file);
    });
},

核心问题代码

少了

js 复制代码
if (this.limit && this.fileList.length + files.length > this.limit) {
    // 异常逻辑处理 建议从调用的业务代码定义好异常逻辑传入并且调用
}

完整逻辑

js 复制代码
uploadFiles (files) {
    if (this.limit && this.fileList.length + files.length > this.limit) {
    // 异常逻辑处理 建议从调用的业务代码定义好异常逻辑传入并且调用
    }
    let postFiles = Array.prototype.slice.call(files);
    if (!this.multiple) postFiles = postFiles.slice(0, 1);

    if (postFiles.length === 0) return;

    postFiles.forEach(file => {
        this.upload(file);
    });
},

问题已经找到了,但是如何接入业务代码项目中呢

考虑方案

  • 直接改node_modules中源代码
    • 不建议,直接否定 ,理由如下
      • 在node_modules中源代码后需要,其他成员更新node_modules中源代码
      • 无法提交到git中,因为不可能将node_modules放到git上
      • 后期更新插件版本就会替换整个文件夹
      • 直接否定
  • 修改插件代码后放到私有服务器
    • 不建议,直接否定,理由如下
      • 后期插件版本升级了,如果想使用高版本的iview组件库,只能直接覆盖代码
      • 接入私服后,安装依赖只能在内网,极其不方便
  • 直接从iview组件库的upload组件中捞一份 upload的源代码,然后再新的文件中修改
    • 最优解
      • 以上问题都不会有
      • 可扩展性强,且不会影响其他逻辑

如何调用组件

  • 封装好组件后,直接调用
  • 同时传递,limit(限制数量),以及数量超出的执行异常回调函数即可

致谢

  • 感谢项目组给予我挑战自己的机会
  • 感谢iview写出了让我感到诧异的bug
    传递,limit(限制数量),以及数量超出的执行异常回调函数即可

致谢

  • 感谢项目组给予我挑战自己的机会
  • 感谢iview写出了让我感到诧异的bug
  • 感谢element ui 的完美源代码给予了我学习和参考并实践的机会
相关推荐
染指11107 小时前
103.RAG-LLamaIndex后端rag问答-聊天接口
前端·javascript·vue.js·人工智能
单线程_0114 小时前
从案例分析 Vue3 Tokenizer+Parser 源码三
前端·javascript·vue.js
小磊哥er16 小时前
深入解构Claude Code - 第 8 篇 · 数据放哪、钱怎么算
javascript·ai编程
kyriewen18 小时前
我装了30多个Skill,给AI安排了8个岗位
前端·javascript·ai编程
默_笙20 小时前
🔥 让 AI 帮我写完整个 Next.js 博客:框架就是 AI 的"上下文 buff"
前端·javascript
喵本喵叁肆1 天前
06-M6-部门过滤与综合研判-从问答机到研判助手
前端·javascript·jquery
এ慕ོ冬℘゜1 天前
JavaScript学习心得:从只会语法,到真正会写业务逻辑
开发语言·javascript·ecmascript
এ慕ོ冬℘゜1 天前
jQuery 核心方法
前端·javascript·jquery
阳火锅1 天前
老板要周报?我说不用,代码提交就是进度
前端·javascript·vue.js