在使用element-ui的upload组件时,由于业务逻辑复杂,我们有时需要使用自定义的http-request属性来覆盖组件默认的上传行为,在使用这个属性的时候,我发现:原本定义好的各种钩子函数(除了on-exceed,on-remove)都没有被执行。导致了文件上传进度被无视,以及也无法处理上传错误,那么使用自定义上传http-request属性后,如何设置钩子函数呢,我进行了一番研究🤔。

可以看到官方文档中并没有给到这个http-request的可选值和默认函数,这就得自己去摸索搜索咯😒。

http-request
http-request

在定义了自定义上传方法后,我想着这些element组件大部分的方法都会有默认参数,试着打印看看🧐

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!-- 省略 -->
<el-upload action
ref="uploader"
:limit="item.fileLimit"
:file-list="fileList"
:multiple="item.fileLimit > 1"
:on-remove="removeImg"
:on-exceed="handleExceed"
:accept="fileTypeInfo.accept"
:disabled="item.value.length === item.fileLimit"
:on-success="handleUploadSuccess"
:on-error="handleUploadError"
:http-request="uploadFile">
<el-button size="small"
:disabled="item.value.length === item.fileLimit"
type="primary">点击上传
</el-button>
<div slot="tip"
class="el-upload__tip">只能上传{{fileTypeInfo.label}}文件,且不超过{{item.fileMaxSize}}M
</div>
</el-upload>
<!-- 省略 -->
1
2
3
4
5
6
7
8
9
10
export default {
// ...
methods: {
uploadFile(config) {
console.log(config)
// ...
},
// ...
}
}

惊喜地发现其中有好几个钩子函数:onError, onProgress, onSuccess

uploader-config
uploader-config

于是又看起了文档里对应的钩子函数,试着往里面传对应的参数,发现可以用这些钩子函数啦!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
export default {
// ...
methods: {
uploadFile(config) {
const file = config.file
const { size, type, name } = file
// 判断文件大小是否超出限制 这里做了before-upload里的活
const isLtLimit = file.size / 1024 / 1024 < this.item.fileMaxSize
if (!isLtLimit) {
this.$message({
type: 'error',
message: `${this.fileTypeInfo.label}大小不能超过${this.item.fileMaxSize}MB!`,
customClass: 'message-preview'
})
return false
} else {
let formData = new FormData()
formData.append('file', file) //图像文件列表
formData.append('fileName', name)
formData.append('digest', '销售中台工单上传文件')
formData.append('token', null)
// 开始进度条,从0开始, 这里是干了on-progress钩子里的事
config.onProgress({ percent: 0 })
// 开始上传
uploadFile(formData)
.then(res => {
let fileUrl = res.fileUrl
let param = {
path: 'workOrderPicture',
fileUrl,
fileName: name
}
// 控制进度,上传文件完成,还要继续处理,progress给到了50%
// 下面业务转化链接为有域名的(此项目业务需求,需要将上传文件返回的url再处理一下),请根据自己业务模仿progress进度
config.onProgress({ percent: 50 })
transformFileUrl(param)
.then(response => {
console.log(response.data)
// 处理上传成功,上传进度会展示√标志
config.onSuccess(response.data)
})
.catch(err => {
// 上传失败
config.onError('上传失败')
})
})
.catch(err => {
config.onError('上传失败')
})
}
},
removeImg(file, fileList) {
this.item.value = fileList
this.$store.commit('toggleSubmitDisabled', false)
},
handleExceed() {
this.$message({
type: 'error',
message: '超过文件数量限制',
customClass: 'message-preview'
})
},
handleUploadError(err, file, fileList) {
console.log('err', err, file, fileList)
this.$refs[this.item.key + 'uploader'].clearFiles()
this.item.value = []
},
handleUploadSuccess(res, file, fileList) {
console.log(file, fileList)
if (fileList.every(item => !!item.response)) {
this.$store.commit('toggleSubmitDisabled', false)
}
this.item.value.push(res.url)
}
}
}

对应的onProgress钩子生效了!

uploader-progress
uploader-progress

这样upload组件的钩子函数就能正常使用啦!😁 Tip: onExceed、onRemove钩子在用了http-request时候也能正常调用,要注意的是,在自定义上传方法中调用onSuccess和onError时,是会调用upload实例上声明的钩子函数的,所以还是有必要定义对应的处理上传成功和失败的方法的。