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 的完美源代码给予了我学习和参考并实践的机会
相关推荐
满怀1015几秒前
【Vue 3全栈实战】从响应式原理到企业级架构设计
前端·javascript·vue.js·vue
伟笑32 分钟前
elementUI 循环出来的表单,怎么做表单校验?
前端·javascript·elementui
确实菜,真的爱1 小时前
electron进程通信
前端·javascript·electron
魔术师ID3 小时前
vue 指令
前端·javascript·vue.js
Clown953 小时前
Go语言爬虫系列教程 实战项目JS逆向实现CSDN文章导出教程
javascript·爬虫·golang
星空寻流年4 小时前
css3基于伸缩盒模型生成一个小案例
javascript·css·css3
waterHBO5 小时前
直接从图片生成 html
前端·javascript·html
EndingCoder5 小时前
JavaScript 时间转换:从 HH:mm:ss 到十进制小时及反向转换
javascript
互联网搬砖老肖5 小时前
React组件(一):生命周期
前端·javascript·react.js
HCl+NaOH=NaCl+H_2O6 小时前
Quasar组件 Carousel走马灯
javascript·vue.js·ecmascript