el-upload
是 Element Plus 提供的文件上传组件,支持多种上传方式和丰富的配置选项。下面我将详细解析如何使用它实现图片上传功能。
1. 基本用法
<template>
<el-upload
action="/api/upload" // 上传地址
list-type="picture-card" // 显示为图片卡片
:on-preview="handlePreview" // 点击已上传文件时的回调
:on-remove="handleRemove" // 移除文件时的回调
:on-success="handleSuccess" // 上传成功回调
:on-error="handleError" // 上传失败回调
:file-list="fileList" // 已上传文件列表
>
<i class="el-icon-plus"></i>
</el-upload>
</template>
<script setup>
import { ref } from 'vue';
const fileList = ref([]);
const handlePreview = (file) => {
console.log('预览文件:', file);
};
const handleRemove = (file, fileList) => {
console.log('移除文件:', file, fileList);
};
const handleSuccess = (response, file, fileList) => {
console.log('上传成功:', response, file, fileList);
};
const handleError = (err, file, fileList) => {
console.error('上传失败:', err, file, fileList);
};
</script>
2. 关键属性详解
上传行为相关
action
: 必填,上传的URL地址method
: 上传方法,默认为’post’data
: 上传时附带的额外参数(对象或函数)headers
: 设置上传的请求头部with-credentials
: 是否携带cookie,默认为false
文件限制相关
multiple
: 是否支持多选文件,默认为falseaccept
: 接受上传的文件类型(如"image/*")limit
: 最大允许上传个数file-list
: 已上传的文件列表auto-upload
: 是否在选取文件后立即上传,默认为true
显示相关
list-type
: 文件列表展示方式,可选值:text
(默认)picture
picture-card
drag
: 是否启用拖拽上传
3. 完整示例(带表单验证)
<template>
<el-upload
action="/api/upload"
list-type="picture-card"
:file-list="fileList"
:on-preview="handlePreview"
:on-remove="handleRemove"
:on-success="handleSuccess"
:on-error="handleError"
:before-upload="beforeUpload"
:limit="3"
:on-exceed="handleExceed"
accept="image/*"
>
<i class="el-icon-plus"></i>
<template #tip>
<div class="el-upload__tip">
只能上传jpg/png文件,且不超过500KB
</div>
</template>
</el-upload>
</template>
<script setup>
import { ref } from 'vue';
import { ElMessage } from 'element-plus';
const fileList = ref([]);
const handlePreview = (file) => {
console.log('预览:', file);
};
const handleRemove = (file, files) => {
console.log('移除:', file, files);
};
const handleSuccess = (response, file, files) => {
ElMessage.success('上传成功');
console.log('成功:', response, file, files);
};
const handleError = (err, file, files) => {
ElMessage.error('上传失败');
console.error('失败:', err, file, files);
};
const beforeUpload = (file) => {
const isJPGorPNG = file.type === 'image/jpeg' || file.type === 'image/png';
const isLt500KB = file.size / 1024 < 500;
if (!isJPGorPNG) {
ElMessage.error('只能上传JPG/PNG格式的图片!');
return false;
}
if (!isLt500KB) {
ElMessage.error('图片大小不能超过500KB!');
return false;
}
return true;
};
const handleExceed = (files, fileList) => {
ElMessage.warning(`最多只能上传3张图片,您选择了${files.length}张,共${files.length + fileList.length}张`);
};
</script>
<style>
.el-upload__tip {
margin-top: 7px;
color: #666;
font-size: 12px;
}
</style>
4. 手动上传实现
如果需要手动控制上传时机:
<template>
<el-upload
ref="uploadRef"
action="/api/upload"
:auto-upload="false"
:file-list="fileList"
:on-success="handleSuccess"
>
<template #trigger>
<el-button type="primary">选择文件</el-button>
</template>
<el-button type="success" @click="submitUpload">开始上传</el-button>
</el-upload>
</template>
<script setup>
import { ref } from 'vue';
const uploadRef = ref();
const fileList = ref([]);
const submitUpload = () => {
uploadRef.value.submit();
};
const handleSuccess = (response) => {
console.log('上传成功:', response);
};
</script>
5. 自定义上传实现
如果需要完全自定义上传逻辑(如使用axios):
<template>
<el-upload
action="#"
:http-request="customRequest"
:file-list="fileList"
>
<el-button type="primary">点击上传</el-button>
</el-upload>
</template>
<script setup>
import { ref } from 'vue';
import axios from 'axios';
const fileList = ref([]);
const customRequest = async (options) => {
const { file, onProgress, onSuccess, onError } = options;
const formData = new FormData();
formData.append('file', file);
try {
const res = await axios.post('/api/upload', formData, {
onUploadProgress: (progressEvent) => {
const percent = Math.round(
(progressEvent.loaded * 100) / progressEvent.total
);
onProgress({ percent });
}
});
onSuccess(res.data);
} catch (err) {
onError(err);
}
};
</script>
6. 常见问题解决方案
问题1: 如何获取上传后的文件URL?
在on-success
回调中,服务器应返回文件访问URL,然后可以存储到fileList
中:
const handleSuccess = (response, file) => {
file.url = response.url; // 假设服务器返回{url: '...'}
};
问题2: 如何限制文件大小和类型?
使用before-upload
钩子:
const beforeUpload = (file) => {
const isImage = file.type.startsWith('image/');
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isImage) {
ElMessage.error('只能上传图片!');
return false;
}
if (!isLt2M) {
ElMessage.error('图片大小不能超过2MB!');
return false;
}
return true;
};
问题3: 如何显示上传进度?
组件内置了进度条显示,也可以通过on-progress
回调自定义处理:
:on-progress="handleProgress"
const handleProgress = (event, file, fileList) => {
console.log('上传进度:', event.percent);
};
7. 最佳实践建议
-
服务器响应格式:保持一致的响应格式,如
{code: 200, data: {url: '...'}, message: 'success'}
-
安全考虑:
- 后端应验证文件类型(不能仅依赖前端验证)
- 对上传文件进行病毒扫描
- 限制上传文件大小
-
用户体验:
- 提供清晰的错误提示
- 显示上传进度
- 对于大文件,考虑分片上传
-
性能优化:
- 图片上传前可进行压缩
- 使用CDN加速上传
通过以上配置和方法,你可以灵活地实现各种图片上传需求。根据实际项目情况选择最适合的实现方式。