Vue3上传组件封装


后台项目里面上传功能也很常见,头像、封面、附件、合同文件都可能会用到,所以这里记录一下 Vue3 中上传组件的封装

上传看起来只是选择文件,但是在真实项目里面会遇到很多细节。

比如:

  1. 单图上传
  2. 多图上传
  3. 文件上传
  4. 上传数量限制
  5. 新增时清空
  6. 编辑时回填
  7. 保存时字段格式统一

所以我这次在后台模板里面整理了图片上传和文件上传两个组件。

图片上传

图片上传使用的是 UploadImgMore

单图上传:

1
2
3
4
5
6
7
8
9
<UploadImgMore
ref="singleUploadRef"
mock-upload
:more-length="1"
:upload-type="1"
:input-width="118"
:input-height="118"
@updataImg="updateSingleImg"
/>

多图上传:

1
2
3
4
5
6
7
8
9
10
<UploadImgMore
ref="multiUploadRef"
mock-upload
multiple
:more-length="4"
:upload-type="1"
:input-width="94"
:input-height="94"
@updataImg="updateMultiImg"
/>

这里几个参数比较常用:

  1. more-length:最多上传几个
  2. multiple:是否支持多选
  3. input-width:上传框宽度
  4. input-height:上传框高度
  5. mock-upload:模板演示时使用 mock 上传

文件上传

文件上传使用的是 UploadFile

1
2
3
4
5
6
7
8
<UploadFile
ref="fileUploadRef"
mock-upload
:more-length="2"
@updataImg="updateFileList"
>
支持文档、压缩包、安装包等附件示例。
</UploadFile>

文件上传和图片上传最后都统一返回文件列表。

统一字段

不同上传组件或者不同后端返回的字段可能不一样。

有的叫 url,有的叫 oss_url

有的叫 name,有的叫 oss_key

所以保存前最好统一一下字段:

1
2
3
4
5
6
normalizeUploadList(fileList = []) {
return fileList.map((item) => ({
oss_key: item.oss_key || item.name,
oss_url: item.oss_url || item.url
}));
}

这样后面业务保存的时候,就不用关心组件内部返回了什么字段。

新增

新增时需要把表单和上传组件都清空。

1
2
3
4
5
6
7
8
9
openCreate() {
this.formData = createDefaultForm();
this.createDialog = true;

this.$nextTick(() => {
this.resetDialogUpload();
this.$refs.formRef?.clearValidate();
});
}

这里需要等弹窗打开之后再调用组件方法,所以放在 $nextTick 中。

编辑回填

编辑时最重要的是回填。

表单数据可以直接复制,但是上传组件里面的文件列表需要手动初始化。

1
2
3
4
5
6
7
8
9
10
11
edit(row) {
this.formData = JSON.parse(JSON.stringify(row));
this.createDialog = true;

this.$nextTick(() => {
this.$refs.dialogCoverRef?.initUpload(this.formData.coverList);
this.$refs.dialogImagesRef?.initUpload(this.formData.imageList);
this.$refs.dialogFileRef?.initFile(this.formData.fileList);
this.$refs.formRef?.clearValidate();
});
}

图片使用 initUpload,文件使用 initFile

这样打开编辑弹窗时,之前上传过的图片和文件就能正常显示出来。

重置组件

弹窗关闭时也需要重置上传组件。

1
2
3
4
5
resetDialogUpload() {
this.$refs.dialogCoverRef?.resetFields();
this.$refs.dialogImagesRef?.resetFields();
this.$refs.dialogFileRef?.resetFields();
}

不然可能会出现新增时还显示上一次编辑图片的问题。

表单校验

如果封面图是必填,可以把上传结果放进表单字段里。

1
2
3
4
updateDialogCover(fileList) {
this.formData.coverList = this.normalizeUploadList(fileList);
this.$refs.formRef?.validateField('coverList');
}

上传后主动触发表单校验,这样用户上传图片后错误提示能及时消失。

保存

保存的时候只保存整理后的字段。

1
2
3
4
5
6
7
8
9
10
11
save() {
this.$refs.formRef.validate((valid) => {
if (!valid) {
return;
}

const data = JSON.parse(JSON.stringify(this.formData));

// 调接口保存 data
});
}

真实项目里面这里换成接口请求就可以了。

mock上传

模板里面加了 mock-upload,主要是为了让示例页面不依赖真实接口。

新项目接入真实后端时,可以去掉 mock-upload,然后在上传组件里面接入真实的 OSS token 或上传接口。

总结

上传组件封装时,我觉得最容易忽略的是编辑回填。

只处理新增上传不难,难的是保证下面几件事都正常:

  1. 新增时为空
  2. 编辑时能回填
  3. 删除后字段同步
  4. 上传后表单校验同步
  5. 保存字段格式统一

这些处理好以后,图片上传、附件上传、封面上传这些场景基本都能复用。

以上就是我对 Vue3 上传组件封装的一些理解,如有错误,欢迎大佬指出。

-------------本文结束感谢您的阅读-------------