先说明几点:1. 使用Vue 2.x。2. 这几个例子是比较适合我自己项目场景的方案,主要为了记录下,仅供参考。样式有引入部分覆盖element-ui的公共样式,因此光用我组件里scoped的样式显示效果不会完全一样。然后单图上传是模拟了element-ui 两种文件列表的样子,实际上属性设置为:show-file-list="false"
,移除功能也是额外定义而非传值实现的。需要留下心。
一、单图上传(父子组件图片地址双向绑定)
我们先看功能和效果。大致分点击按钮上传和拖拽上传,上传后都可以预览(预览弹窗宽度可传参dialogWidth: String
自定义)
1. 点击按钮上传 (不传 drag
参数)
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
钩子,也不要再调用this.$refs.upload.submit()
。同时on-success
和on-error
也都无用武之地了。
文件状态改变时的钩子on-change
也可以帮助我们方便地获取文件数据。on-change
事件触发的次数也是根据选取图片的张数来的,我们可以在此处理验证文件格式等,代替自动上传时before-upload
进行的逻辑。
action
是el-upload的必选属性,但手动上传的情况这个值其实无意义了,我们可以设置为空字符串或者任意字符 :action="''"
再然后,让用户自己选取图片再确认上传这个功能似乎不太合理(头像上传这种单图的情况相对适用)。一方面直观简洁的操作体验更好,还有可能造成部分场景逻辑不连贯:比如图片上传只是表单的一项而已,最终提交表单的时候,用户选取了文件但没有点击上传,是他/她放弃传还是忘记了呢?所以这种情况我们把上传事件放在提交表单里。
说了这么多,你是不是想说,don't bb,show me the code
具体封装好的
MultiUpload
组件代码如下:
选取文件
将单张图片拖到
此处,或点击上传
只能上传jpg/png/gif文件,且不超过2M。
图片列表中已经上传成功的图片(有绿色✓),点击图片名称可以预览大图
父组件使用
export default {
name: 'Clothing',
data() {
return {
newClothing: {
// ...
photoSrc: ''
}
},
method:
}
丑丑的样式就先这样了,懒得再改了,心lui了
在使用sass-loader预处理器的情况下,覆盖element-ui样式的时候遇到了坑,指路:[Vue] scoped覆盖第三方或子组件样式无效
可以看出这两个组件和elementUI大部分是借鉴UI的关系,主要功能大多自行实现,因此稍微修改下就可以应用到大部分库(如vuetify、iview)。
以上均为个人拙见,功能/业务逻辑大家觉得有不合理之处或者更好的处理方法,欢迎留言指点。