使用 Vue 3 和 el-upload
实现文件上传与自定义粘贴板图像上传功能
在这篇文章中,我们将详细介绍如何在 Vue 3 项目中使用 Element Plus 的 el-upload
组件实现文件上传。此实现不仅支持多种文件类型(如图片、视频、PDF 和 Excel 文件),还提供了从剪贴板直接粘贴图片上传的功能。通过自定义预览模板和手动管理文件列表,我们实现了灵活的上传和展示功能。
1. 基本的 el-upload
组件设置
首先,el-upload
组件是一个高度灵活的文件上传组件。我们可以通过多个 props 自定义其行为和样式。
ini
<el-upload
ref="uploadRef"
:action="action"
:headers="headers"
:multiple="multiple"
:data="data"
:name="name"
:with-credentials="withCredentials"
:show-file-list="showFileList"
:drag="drag"
:accept="accept"
:list-type="listType"
:auto-upload="autoUpload"
:file-list="fileList"
:http-request="httpRequest"
:disabled="disabled"
:limit="limit"
@success="handleUploadSuccess"
@error="handleUploadError"
@remove="handleFileRemove"
@preview="handlePictureCardPreview"
@change="handleFileChange"
:before-upload="beforeUpload"
/>
2. 自定义文件预览模板
我们可以通过插槽来自定义上传文件的预览模板。例如,根据文件类型显示不同的预览样式,如图片、视频、Excel 文件或 PDF 文件。
xml
<template #file="{ file }">
<div>
<img v-if="isImage(file.url)" class="el-upload-list__item-thumbnail" :src="file.url" alt="" />
<video v-else-if="isVideo(file.url)" controls style="width: 100%; height: 100%">
<source :src="file.url" type="video/mp4" />
</video>
<el-button v-else-if="isExcelFile(file.url)" size="default" type="warning">
<el-icon><ele-Download /></el-icon>{{ file.originalName }}
</el-button>
<iframe v-else-if="isPdf(file.url)" :src="file.url" width="100%" height="100%"></iframe>
<span class="el-upload-list__item-actions">
<span @click="handlePictureCardPreview(file)">
<el-icon><ele-ZoomIn /></el-icon>
</span>
<span @click="handleDownload(file)">
<el-icon><ele-Download /></el-icon>
</span>
</span>
</div>
</template>
3. 粘贴板图片自动上传功能
在很多应用场景下,用户直接复制截图或图片并粘贴上传是一个非常实用的功能。我们通过监听 paste
事件来实现该功能。
typescript
<div class="paste-box d-flex a-center j-center" v-if="!disabled" @paste="onPaste">
<span class="paste-tip-text">Ctrl+V<br />可粘贴截图</span>
</div>
在 JavaScript 逻辑中,通过 onPaste
函数处理粘贴事件。我们提取粘贴内容中的图像文件,并调用 el-upload
组件的 submit
方法来自动上传。
ini
const onPaste = (event: ClipboardEvent) => {
if (props.disabled) return;
const clipboardData = event.clipboardData;
if (clipboardData) {
const items = clipboardData.items;
for (let i = 0; i < items.length; i++) {
const item = items[i];
if (item.kind === 'file' && item.type.startsWith('image/')) {
const file = item.getAsFile();
if (file) {
uploadRef.value.handleStart(file);
uploadRef.value.submit();
}
}
}
}
};
4. 文件上传成功后的处理
在文件上传成功后,我们需要更新文件列表,确保列表中不包含临时的 blob:
URL。这里我们自定义了 handleUploadSuccess
函数来处理文件上传的成功响应,并使用 replaceBlobUrls
方法来替换文件列表中的临时 URL。
typescript
const handleUploadSuccess = (response: any, file: UploadUserFile, files: UploadFiles) => {
emit('upload-success', response, file, replaceBlobUrls(files));
fileList.value = replaceBlobUrls(files);
emit('update:fileList', fileList.value);
};
const replaceBlobUrls = (array: any[]) => {
const updatedArray = array.map((item) => {
if (item.url && item.url.includes('blob:')) {
return item.response.data;
}
return item;
});
return Array.from(new Set(updatedArray.map(item => JSON.stringify(item)))).map(item => JSON.parse(item));
};
5. 文件删除、预览和下载功能
我们还实现了文件删除、预览和下载的功能。通过 handleFileRemove
函数,我们可以从文件列表中删除特定文件。对于文件预览,我们实现了一个对话框展示,并根据文件类型(图片、视频等)进行不同的展示。
ini
const handleFileRemove = (file: UploadUserFile) => {
fileList.value = fileList.value.filter((f) => f !== file);
emit('file-remove', file);
emit('update:fileList', fileList.value);
};
const handlePictureCardPreview = (file: UploadUserFile) => {
index.value = arrayimg(fileList.value, file.url);
dialogImageUrl.value = file.url;
dialogVisible.value = true;
};
const handleDownload = (file: UploadUserFile) => {
const link = document.createElement('a');
link.href = file.url;
link.download = file.originalName || 'download';
link.click();
};
总结
通过使用 Vue 3 和 Element Plus 的 el-upload
组件,我们可以非常灵活地处理多种文件类型的上传、预览、删除和下载功能。剪贴板图片自动上传的功能为用户带来了更便捷的体验。在项目中,我们可以根据需求进一步扩展这些功能,如添加上传进度、错误处理和更多文件类型支持。