前言
很久没写文章了,主要还是工作太忙了。这篇文章记录一下,我在工作中遇到的问题,及解决的办法,也方便以后参考。
UI
要我实现的效果图如下:
上传图片后会显示重新上传
按钮,且文字位置会变,当然这很简单。
有难度的地方就是:1.这是个单文件上传;2.需要校验图片是否满足要求。
2都好解决,但也要小心处理。对于1,很多人会在el-upload
组件中加上参数:limit="1"
,我起先也是这么尝试的,是无法上传第二张图片了,但是那个带+
号的方框依旧会在,你依旧可以选择图片,只是无法上传,WTF
,不能容忍,极差的体验。后面在对接后台的时候,我发现我的请求还要设置请求头headers
带上Authorization_token
认证的token
信息及设置Content-Type
字段为multipart/form-data
,所以我还得走自定义请求。
实现
别人的问题有时候也是你的问题,只是你还没遇到。不多说,直接贴关键代码:
vue
模板部分:
<el-form-item label="商品图片" prop="goodsPic" style="width: 150%;" class="is-required">
<el-upload
ref="upload"
action
:class="{hide: !hideUpload}"
list-type="picture-card"
accept="image/png, image/jpeg, image/gif"
:auto-upload="false"
:before-upload="beforeUpload"
:on-change="uploadChange"
:http-request="httpRequest"
:file-list="fileList"
>
<i ref="file" slot="trigger" class="el-icon-plus" />
<div slot="file">
<img class="el-upload-list__item-thumbnail" :src="form.goodsPic">
<span class="el-upload-list__item-actions">
<span class="el-upload-list__item-preview" @click="previewVisible = true">
<i class="el-icon-zoom-in" />
</span>
</span>
</div>
</el-upload>
<el-button v-if="!hideUpload" @click="$refs.file.click()">重新上传</el-button>
<span :class="{tip: hideUpload}" style="color: #C0C4CC;margin-left: 10px;">要求:1M以内,格式 jpeg、gif、png;尺寸不小于800*800px</span>
<el-dialog :visible.sync="previewVisible" append-to-body width="740px" top="5vh">
<img width="700px" height="700px" :src="form.goodsPic">
</el-dialog>
</el-form-item>
JS
部分:
export default {
data() {
return {
form: {
goodsPic: '',
},
fileList: [], // 上传的图片列表,回显时会有用
previewVisible: false, // 图片预览弹层是否显示
hideUpload: true, // 是否隐藏重新上传按钮
}
},
created() {
if (this.type) { // 编辑时
this.fileList = [{ url: this.form.goodsPic }] // 回显时图片的固定格式
this.hideUpload = false
}
},
methods: {
httpRequest(param) { // 自定义图片上传
uploadImg(param) // 图片上传的异步方法
.then(res => {
this.form.goodsPic = res.data.filePath
})
.catch(err => {
this.$message.error(err)
})
},
uploadChange() { // 选取了图片就进行上传
this.$refs.upload.submit()
},
beforeUpload(file) { // 上传了图片前的校验
const isLt1M = file.size / 1024 / 1024 < 1
if (!isLt1M) {
this.$message.error('上传的图片大小不能超过 1MB!')
}
const isSize = new Promise(function(resolve, reject) {
const width = 800
const height = 800
const _URL = window.URL || window.webkitURL
const img = new Image()
img.onload = function() {
const valid = img.width >= width && img.height >= height
valid ? resolve() : reject()
}
img.src = _URL.createObjectURL(file)
}).then(() => {
this.hideUpload = false
if (this.$refs.upload.uploadFiles.length > 1) this.$refs.upload.uploadFiles.splice(0, 1)
return file
}, () => {
this.$message.error('上传的图片尺寸应不小于800*800px')
return Promise.reject()
})
return isLt1M && isSize
}
}
}
css
部分
.hide >>>.el-upload--picture-card {
display: none;
}
对于上传请求的封装:
export function uploadImg(data) {
const formData = new FormData()
formData.append('file', data.file)
return request({
url: '/image/upload',
method: 'post',
data: formData,
headers: {
'Content-Type': 'multipart/form-data'
}
})
}
解析
单图片上传,我没有添加限制参数:limit="1"
,而是在文件满足要求后,让上传文件的列表每次从头部减1
,用的数组的splice
方法,规避数组的检测更新问题。其次一定要添加on-change
属性,来触发上传事件。如果要添加环形进度条,模拟组件原来的那种效果,我的想法是在el-upload
上层覆盖个el-progress
组件,然后在请求中设置监听文件上传进度来渲染进度条,具体的网上百度,我也没实现这个效果😂😂😂