Element UI el-upload 二次封装图片上传组件(可预览、可批量,含手动上传)

先说明几点:1. 使用Vue 2.x。2. 这几个例子是比较适合我自己项目场景的方案,主要为了记录下,仅供参考。样式有引入部分覆盖element-ui的公共样式,因此光用我组件里scoped的样式显示效果不会完全一样。然后单图上传是模拟了element-ui 两种文件列表的样子,实际上属性设置为:show-file-list="false",移除功能也是额外定义而非传值实现的。需要留下心。

一、单图上传(父子组件图片地址双向绑定)

我们先看功能和效果。大致分点击按钮上传拖拽上传,上传后都可以预览(预览弹窗宽度可传参dialogWidth: String自定义)

1. 点击按钮上传 (不传 drag 参数)
没有图片数据时
有图片数据时
移到按钮右侧出现 x 图标,可用来删除上传的图片
点击 x 弹出确认框
大图预览效果,可自定义预览弹窗宽度
2. 拖拽/点击上传 (传 :drag = "true")

注:拖拽无法限制拖入多张图的操作,但我们设置了:multiple="false",因此只有一张能上传成功。

没有图片数据时

有图片数据时
鼠标移到小预览图上后有两个功能,右边垃圾桶图标可移除图片
点击放大镜大图预览
3. 组件代码

SingleUpload.vue








4. 使用

前提是我已经全局注册upload-single组件,若单独引用别忘了在当前组件导入和注册。然后一般情况同个项目上传地址都是一致的,就写死在上传组件里了。用起来基本只需关注数据字段,代码非常简洁。


export default {
  name: 'Plant',
  data() {
    return {
      newPlant: {
        // ...
        photoSrc: ''    
    }
  }
}

一、批量上传

设置 multiple: true 可以让我们同时选取多个文件,然而上传到action地址的时候,则是选取几个文件便调用几次接口,on-success也会触发相应的次数。处理上传成功返回数据的时候要特别注意。

手动上传相关参数

除此之外,el-upload也支持手动上传。(这在多图的时候很有必要,对用户来说可以在上传前确认一遍选择的资源是否正确,对服务端来说可以节省不必要的开销)
在组件设置:auto-upload="false"ref="upload":http-request="handleUpload"之后,执行this.$refs.upload.submit(),便会触发http-request钩子。如果我们在http-request函数中发起上传请求,则仍是fileList有几个文件就调用几次接口,依旧无法实现在一次请求中上传多个文件。例子如下:


export default {
  name: 'MultiUpload',
  methods: {
    submitUpload() {
      this.$refs.upload.submit()
    },
    handleUpload(params) {
      // 如果在这里写上传业务,有多少张图片就会触发多少次上传请求
      console.log(params)
    },
  }
}
界面效果一
选取两张图片,再点击上传到服务器后http-request钩子打印的参数

如果我们想在选取图片后手动上传,并且提交请求时一次性上传多个文件,就选择放弃http-request钩子,也不要再调用this.$refs.upload.submit()。同时on-successon-error也都无用武之地了。
文件状态改变时的钩子on-change也可以帮助我们方便地获取文件数据。on-change事件触发的次数也是根据选取图片的张数来的,我们可以在此处理验证文件格式等,代替自动上传时before-upload进行的逻辑。
action是el-upload的必选属性,但手动上传的情况这个值其实无意义了,我们可以设置为空字符串或者任意字符 :action="''"
再然后,让用户自己选取图片再确认上传这个功能似乎不太合理(头像上传这种单图的情况相对适用)。一方面直观简洁的操作体验更好,还有可能造成部分场景逻辑不连贯:比如图片上传只是表单的一项而已,最终提交表单的时候,用户选取了文件但没有点击上传,是他/她放弃传还是忘记了呢?所以这种情况我们把上传事件放在提交表单里。

说了这么多,你是不是想说,don't bb,show me the code


具体封装好的MultiUpload组件代码如下:







父组件使用


export default {
  name: 'Clothing',
  data() {
    return {
     newClothing: {
        // ...
        photoSrc: ''    
    }
  },
  method: 
}
左边是我们上传处理后的格式,右边是未上传到服务器的图片格式
批量上传默认样式
批量拖拽上传
大图预览

丑丑的样式就先这样了,懒得再改了,心lui了
在使用sass-loader预处理器的情况下,覆盖element-ui样式的时候遇到了坑,指路:[Vue] scoped覆盖第三方或子组件样式无效

可以看出这两个组件和elementUI大部分是借鉴UI的关系,主要功能大多自行实现,因此稍微修改下就可以应用到大部分库(如vuetify、iview)。
以上均为个人拙见,功能/业务逻辑大家觉得有不合理之处或者更好的处理方法,欢迎留言指点。

你可能感兴趣的:(Element UI el-upload 二次封装图片上传组件(可预览、可批量,含手动上传))