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 的完美源代码给予了我学习和参考并实践的机会
相关推荐
Yaml42 小时前
Spring Boot 与 Vue 共筑二手书籍交易卓越平台
java·spring boot·后端·mysql·spring·vue·二手书籍
前端青山3 小时前
Node.js-增强 API 安全性和性能优化
开发语言·前端·javascript·性能优化·前端框架·node.js
从兄4 小时前
vue 使用docx-preview 预览替换文档内的特定变量
javascript·vue.js·ecmascript
清灵xmf5 小时前
在 Vue 中实现与优化轮询技术
前端·javascript·vue·轮询
薛一半6 小时前
PC端查看历史消息,鼠标向上滚动加载数据时页面停留在上次查看的位置
前端·javascript·vue.js
过期的H2O27 小时前
【H2O2|全栈】JS进阶知识(四)Ajax
开发语言·javascript·ajax
MarcoPage7 小时前
第十九课 Vue组件中的方法
前端·javascript·vue.js
你好龙卷风!!!7 小时前
vue3 怎么判断数据列是否包某一列名
前端·javascript·vue.js
shenweihong9 小时前
javascript实现md5算法(支持微信小程序),可分多次计算
javascript·算法·微信小程序
巧克力小猫猿9 小时前
基于ant组件库挑选框组件-封装滚动刷新的分页挑选框
前端·javascript·vue.js