基于 Element Plus 的文件上传和预览组件实现

使用 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 组件,我们可以非常灵活地处理多种文件类型的上传、预览、删除和下载功能。剪贴板图片自动上传的功能为用户带来了更便捷的体验。在项目中,我们可以根据需求进一步扩展这些功能,如添加上传进度、错误处理和更多文件类型支持。

相关推荐
学不会•1 小时前
css数据不固定情况下,循环加不同背景颜色
前端·javascript·html
活宝小娜3 小时前
vue不刷新浏览器更新页面的方法
前端·javascript·vue.js
程序视点3 小时前
【Vue3新工具】Pinia.js:提升开发效率,更轻量、更高效的状态管理方案!
前端·javascript·vue.js·typescript·vue·ecmascript
coldriversnow3 小时前
在Vue中,vue document.onkeydown 无效
前端·javascript·vue.js
我开心就好o3 小时前
uniapp点左上角返回键, 重复来回跳转的问题 解决方案
前端·javascript·uni-app
开心工作室_kaic4 小时前
ssm161基于web的资源共享平台的共享与开发+jsp(论文+源码)_kaic
java·开发语言·前端
刚刚好ā4 小时前
js作用域超全介绍--全局作用域、局部作用、块级作用域
前端·javascript·vue.js·vue
沉默璇年6 小时前
react中useMemo的使用场景
前端·react.js·前端框架
yqcoder6 小时前
reactflow 中 useNodesState 模块作用
开发语言·前端·javascript
2401_882727576 小时前
BY组态-低代码web可视化组件
前端·后端·物联网·低代码·数学建模·前端框架