在 Element UI 或 Element Plus 中使用 el-upload
组件获取选择的文件,关键在于理解其工作模式(自动上传还是手动上传)并使用正确的钩子函数或属性。
方法类别 | 核心钩子/属性 | 适用场景 | 关键特点 |
---|---|---|---|
自动上传模式 | on-success , on-change |
文件选好后立即自动上传到服务器。 | on-success 在服务器返回成功后触发;on-change 在文件状态改变(包括选择)时立即触发。 |
手动上传模式 | auto-upload="false" + on-change |
需要先选择文件,在特定时机(如表单提交)再触发上传。 | 通过 on-change 收集文件,通过 ref 调用 submit() 方法上传。 |
完全自定义请求 | http-request |
需要完全控制上传请求的逻辑,如使用特定 HTTP 库或添加复杂参数。 | 覆盖组件默认的上传行为,需自行实现请求。 |
💡 关键钩子与属性详解
掌握以下钩子和属性,是灵活使用 el-upload
的基础:
on-change
钩子:这是最常用于获取文件对象的钩子。只要文件列表发生变化(比如用户选择了文件、上传成功、上传失败),它就会被触发。它的回调函数参数(file, fileList)
包含了当前变化的文件对象和最新的文件列表。auto-upload
属性:当其值为false
时,组件在选择文件后不会自动发起上传请求,使你能够手动控制上传时机。http-request
属性:用于覆盖组件默认的 XHR 上传行为。当你使用这个属性时,需要在其函数内自行实现文件上传的逻辑(例如,使用axios
或fetch
)。file-list
属性:用于绑定上传组件的文件列表。你可以通过操作这个数组来读取或控制显示的文件列表。
🛠️ 不同场景的实现方式
1. 自动上传模式
如果你希望用户选择文件后立即上传,可以配置 action
属性(服务器端接口地址),并使用 on-success
或 on-change
钩子来获取文件信息。
<el-upload
action="/your/upload/api"
:on-success="handleSuccess"
:on-change="handleChange"
>
<el-button size="small" type="primary">点击上传</el-button>
</el-upload>
<script>
export default {
methods: {
// 服务器返回成功时触发,适用于需要在服务器确认成功后进行操作的场景
handleSuccess(response, file, fileList) {
console.log('上传成功,服务器返回:', response);
console.log('当前文件:', file);
},
// 文件状态改变时立即触发,适用于需要即时获取文件本地信息(如预览)的场景
handleChange(file, fileList) {
console.log('当前文件(原始File对象):', file.raw); // 关键的原始文件对象
console.log('组件内封装的文件对象:', file);
console.log('当前全部文件列表:', fileList);
}
}
};
</script>
2. 手动上传模式
当你需要用户先选择文件(可能还会进行一些其他操作),然后在某个时间点(如点击"提交"按钮)统一上传时,手动上传模式非常有用。
<el-upload
ref="uploadRef"
action="/your/upload/api"
:auto-upload="false" <!-- 关键:关闭自动上传 -->
:on-change="handleFileChange"
:file-list="fileList"
>
<el-button size="small" type="primary">选择文件</el-button>
</el-upload>
<el-button type="success" @click="submitUpload">开始上传</el-button>
<script>
export default {
data() {
return {
fileList: [] // 用于绑定文件列表
};
},
methods: {
handleFileChange(file, fileList) {
// 文件选择时,可以在这里保存文件信息,但不上传
console.log('已选择文件(等待手动上传):', file.raw);
this.fileList = fileList; // 更新文件列表
},
submitUpload() {
// 通过ref调用submit方法,手动触发上传
this.$refs.uploadRef.submit();
}
}
};
</script>
3. 完全自定义上传请求
对于需要更精细控制(如添加特定请求头、处理特殊响应格式、使用不同的HTTP库)的场景,可以使用 http-request
自定义上传请求。
<el-upload
action="#" <!-- 使用自定义请求时,action可设为占位符 -->
:http-request="customUploadRequest"
:on-change="handleChange"
>
<el-button size="small" type="primary">点击上传</el-button>
</el-upload>
<script>
import { uploadFile } from '@/api/file'; // 导入自己封装的API函数
export default {
methods: {
handleChange(file) {
console.log('要上传的文件:', file.raw);
},
async customUploadRequest(options) {
// options 参数中包含 file, onProgress, onSuccess, onError 等
const { file, onProgress, onSuccess, onError } = options;
const formData = new FormData();
formData.append('file', file); // 创建FormData对象
try {
// 使用自定义的请求(如axios)上传文件
const response = await uploadFile(formData);
// 手动触发成功回调,通知上传组件上传成功
onSuccess(response);
console.log('自定义上传成功:', response);
} catch (error) {
// 手动触发失败回调
onError(error);
console.error('上传失败:', error);
}
}
}
};
</script>
⚠️ 实用提示
- 获取原始文件对象:在
on-change
或on-success
等钩子的file
参数中,file.raw
才是原始的File
对象,包含了完整的文件信息(如文件名、大小、类型等)。组件封装后的file
对象还包含状态、uid等信息。 - 处理多个文件:设置
multiple
属性后,在钩子函数中会通过fileList
参数拿到当前所有文件的数组。 - 本地文件预览:如果需要在上传前在页面中预览图片,可以在
on-change
钩子中,使用URL.createObjectURL(file.raw)
生成一个本地临时 URL 并赋值给img
标签的src
属性。