Giới thiệu
Trong bài viết này, chúng ta sẽ cùng phân tích chi tiết component el-upload của Element Plus. Trước tiên, hãy xem qua một ví dụ cơ bản từ tài liệu chính thức:
<template>
<el-upload
v-model:file-list="fileList"
class="upload-demo"
action="https://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15"
multiple
:on-preview="handlePreview"
:on-remove="handleRemove"
:before-remove="beforeRemove"
:limit="3"
:on-exceed="handleExceed"
>
<el-button type="primary">Click to upload</el-button>
<template #tip>
<div class="el-upload__tip">
jpg/png files with a size less than 500KB.
</div>
</template>
</el-upload>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import type { UploadProps, UploadUserFile } from 'element-plus'
const fileList = ref<UploadUserFile[]>([
{
name: 'element-plus-logo.svg',
url: 'https://element-plus.org/images/element-plus-logo.svg',
},
{
name: 'element-plus-logo2.svg',
url: 'https://element-plus.org/images/element-plus-logo.svg',
},
])
const handleRemove: UploadProps['onRemove'] = (file, uploadFiles) => {
console.log(file, uploadFiles)
}
const handlePreview: UploadProps['onPreview'] = (uploadFile) => {
console.log(uploadFile)
}
const handleExceed: UploadProps['onExceed'] = (files, uploadFiles) => {
ElMessage.warning(
`The limit is 3, you selected ${files.length} files this time, add up to ${
files.length + uploadFiles.length
} totally`
)
}
const beforeRemove: UploadProps['beforeRemove'] = (uploadFile, uploadFiles) => {
return ElMessageBox.confirm(
`Cancel the transfer of ${uploadFile.name} ?`
).then(
() => true,
() => false
)
}
</script>
Các type quan trọng
Chúng ta cùng xem chi tiết hai type quan trọng được import vào:
// UploadProps chứa tất cả các thuộc tính của component Upload
type UploadProps = {
action: string // Địa chỉ upload
headers?: Headers | Record<string, any> // Header của request
method?: string // Phương thức upload, mặc định là post
multiple?: boolean // Cho phép chọn nhiều file
data?: Record<string, any> // Tham số bổ sung khi upload
name?: string // Tên trường file, mặc định là file
withCredentials?: boolean // Gửi cookie cùng request
showFileList?: boolean // Hiển thị danh sách file đã upload
drag?: boolean // Bật tính năng kéo thả
accept?: string // Loại file được chấp nhận
fileList?: UploadUserFile[] // Danh sách file
listType?: 'text' | 'picture' | 'picture-card' // Kiểu hiển thị danh sách
autoUpload?: boolean // Upload tự động
disabled?: boolean // Vô hiệu hóa component
limit?: number // Số file tối đa được phép upload
}
// UploadUserFile định nghĩa cấu trúc dữ liệu của một file
interface UploadUserFile {
name: string // Tên file
url?: string // Đường dẫn file
uid: number | string // ID duy nhất của file
status?: 'ready' | 'uploading' | 'success' | 'fail' // Trạng thái file
size?: number // Kích thước file
raw?: File // Đối tượng File gốc
response?: any // Phản hồi từ server
percentage?: number // Tiến trình upload
}
Về cú pháp TypeScript
Đoạn code này sử dụng cú pháp indexed access types trong TypeScript:
const handleRemove: UploadProps['onRemove'] = (file, uploadFiles) => {
console.log(file, uploadFiles)
}
Cú pháp
UploadProps['onRemove'] cho phép truy xuất type của thuộc tính
onRemove từ interface
UploadProps. Điều này có nghĩa là
handleRemove được định nghĩa như một hàm nhận vào hai tham số:
file là file được thao tác và
uploadFiles là mảng tất cả các file hiện tại.
Cách thức hoạt động
Khi sử dụng el-upload, quy trình diễn ra như sau:
1. Người dùng click vào button được bọc trong el-upload
2. Component kích hoạt một input file ẩn
3. Các hook được gọi theo thứ tự:
before-upload →
on-change →
on-progress →
on-success /
on-error →
on-exceed (nếu vượt quá limit)
Lưu ý quan trọng: Component sử dụng axios làm phương thức gửi request mặc định. Thuộc tính
action là bắt buộc và mặc định sử dụng method POST. Nếu muốn tự xử lý hoàn toàn logic upload, bạn có thể đặt
action="#" và viết logic trong các hook tương ứng.
Upload bằng kéo thả và thủ công
**Upload kéo thả (Drag & Drop):** Bật thuộc tính
drag để kích hoạt tính năng này. Component sẽ lắng nghe các sự kiện kéo thả từ trình duyệt.
**Upload thủ công:** Đặt
:auto-upload="false" để tắt upload tự động. Sau đó gọi phương thức
submit() thông qua ref khi cần thiết:
const uploadRef = ref()
uploadRef.value!.submit()
Kết luận
Việc sử dụng el-upload khá đơn giản. Chỉ cần bọc một button trong component, thiết lập thuộc tính
action trỏ đến URL backend, và xử lý các sự kiện thông qua các hook được cung cấp. Component sẽ tự động xử lý phần gửi request và quản lý trạng thái file.