作为前端小白这几天一直在忙多文件上传的小组件甚是头疼,希望饿了么UI的版本能再跟进一下,upload的坑确实不少。
查了不少资料,看大家伙都是两个按钮实现多文件上传的,而且多类型文件的预览功能的实现有点复杂,实际用户体验中肯定不好,一个按钮能干的事为什么要两个按钮呢。
所以我思来想去决定自己动手做一个单按钮多文件上传的小组件。
以下是h5部分
<template>
<div class="upload-file">
<el-upload
action
:headers="headers"
:http-request="httpRequest"
multiple
:on-change="onChange"
accept=".doc,.docs,.xls,.xlsx,.pdf"
class="upload-file-uploader"
ref="upload"
>
<!-- 上传按钮 -->
<el-button slot="trigger" size="mini" type="primary">选取文件</el-button>
</el-upload>
<!-- 上传成功的文件列表 -->
<transition-group
class="upload-file-list el-upload-list el-upload-list--text"
name="el-fade-in-linear"
tag="ul"
v-if="showFile"
>
<li
:key="index"
class="el-upload-list__item ele-upload-list__item-content"
v-for="(file, index) in responseList"
>
<el-link :href="file.url" :underline="false" target="_blank">
<span class="el-icon-document"> {{ file.fileName }} </span>
</el-link>
<div class="ele-upload-list__item-content-action">
<el-link :underline="false" @click="handleDelete(index)" type="danger"
>X</el-link
>
</div>
</li>
</transition-group>
</div>
</template>
可以说这个组件的c位还得是http- request属性和辅助on-change属性,这两个是实现单按钮上传的关键。
我一开始以为这个单按钮实现起来肯定很容易,只要把另一个点击上传服务器的按钮里的代码转移到http-request中就好了,然后再改成默认自动上传就好了,但事与愿违。若选两个文件就会发两次请求,第一次请求是一个文件,第二次是两个文件(大于两个情况可以以此类推),这和多文件多请求没啥区别。这个坑困扰了我很长时间,难道只能玩两个按钮??
但是上面的需求不好改动,我只能硬着头皮开始测试。解题的关键在于多文件上传中选中几个文件,并不会默认是你选中的个数,而是会从1递增直到你选中的个数。然后就会依次发送递增文件的请求。那么如何让这个UI组件默认我选中的个数呢?
在观察了数次element UI文档后,我看中了on-change这个属性,(原本是想用before- upload这个属性的,但是自定义上传后,这个属性会失效)。想用on-change来记录我选中的文件个数,但是不测不知道,这玩意也是会递增显示。那么如果我在data里固定一个file ListLength(上传文件个数),然后每次选中文件让on-change的参数file List.length去给它赋值,岂不是会覆盖原先的值,得到最终我们想要的选中文件个数。
onChange(file, fileList) {
this.fileListLength = fileList.length; //选中文件个数
},
到此单文件上传的关键已经解决了,以下就是自定义上传http-request的实现了。
//自定义上传
httpRequest(file) {
const uploadFile = file.file;
const { name, size } = uploadFile;
this.md5file(uploadFile).then((code) => {
const params = {
fileName: name,
hashCode: code,
};//对文件加密
this.desc.files.push(params);
this.fileList.push(uploadFile);
const formData = new FormData();
formData.append("desc", JSON.stringify(this.desc));
//筛选出选中的文件只发一次请求
if (this .fileList.length === this.fileListLength) {
for (let i = 0; i < this.fileList.length; i++) {
formData.append("files", this.fileList[i]);
}
axios({
method: "POST",
url: this.uploadFileUrl,
data: formData,
headers: this.headers
}).then((res) => {
if (res.data.code === 200) {
this.$message.success(res.data.msg);
this.responseList.push.apply(
this.responseList,
res.data.list
);
this.$refs.upload.clearFiles();
} else {
this.$message.error("上传失败");
this.$refs.upload.clearFiles();
}
});
}
});
},
搞定收工,第一次写博客,多有疏漏,欢迎各位大佬指正