Vue3封装一个Element的自定义上传组件
封装一个ElementPlus的自定义上传组件
写在前面,工作中要封装一个文件上传组件,想着以后肯定也能用得到,就给记录了下来
文章通篇借鉴的是这位大佬的,有需要的可以去看看
https://blog.51cto.com/u_15295608/3527047
直接上代码:
先看样式:
就是这样子了!!!,这是个弹窗的形式,有空我再整个无弹窗的
代码在此:
- 首先创建一个NewUpload.vue组件
<template>
<el-dialog title="上传文件" v-model="visible" width="800px" :close-on-click-modal="false" @close="cancel">
<el-upload
ref="upload"
:auto-upload="false"
action="#"
:drag="true"
:before-upload="handleBeforeUpload"
v-model:file-list="fileList"
:limit="limit"
method="put"
multiple
:accept="accept"
:on-error="handleUploadError"
:on-exceed="handleExceed"
:on-remove="handleDelete"
:on-success="handleUploadSuccess"
:show-file-list="true"
class="upload-file-uploader"
:http-request="handleHttpRequest"
>
<!-- 上传按钮-->
<el-button solt="trigger" suze="small" type="primary">上传文件</el-button>
<!--上传提示-->
<div class="el-upload__tip" v-if="isShowTip">
<template v-if="fileSize">大小不超过<b style="color: #f56c6c">{{ fileSize }}MB</b></template>
<template v-if="fileType">格式为<b style="color: #f56c6c">{{ fileType.join('/') }}</b></template>
的文件
</div>
</el-upload>
<transition-group class="upload-file-list el-upload-list el-upload-list--text" name="el-fade-in-linear" tag="ul">
<li :key="file.uid" class="el-upload-list__item ele-upload-list__item-content" v-for="(file, index) in list">
<el-link :href="file.url" :underline="false" target="_blank">
<span class="el-icon-document"> {{ getFileName(file.name) }} </span>
</el-link>
<div class="ele-upload-list__item-content-action">
<el-link :underline="false" @click="handleDelete(index)" type="danger">删除</el-link>
</div>
</li>
</transition-group>
<template #footer>
<slot name="footer">
<el-button style="margin-left: 10px;" :disabled="fileList.length<1" size="default" type="success"
@click="submitUpload">上传服务器
</el-button>
</slot>
</template>
</el-dialog>
</template>
<script setup>
import {ElMessage} from "element-plus";
const props = defineProps({
list: {
type: Array,
default: () => []
},
limit: {
type: Number,
default: 3
},
// 大小限制(MB)
fileSize: {
type: Number,
default: 2,
},
// 文件类型, 例如['png', 'jpg', 'jpeg']
fileType: {
type: Array,
default: () => [".jpg", ".jpeg", ".png", ".doc", ".xls", ".xlsx", ".ppt", ".txt", ".pdf"],
},
// 是否显示提示
isShowTip: {
type: Boolean,
default: true
},
})
const upload = ref()
const fileList = ref([])
const accept = ref('')
const visible = ref(false)
const emit = defineEmits(['input'])
onMounted(() => {
if (props.list.length > 0) {
fileList.value = props.list
}
props.fileType.forEach(el => {
accept.value += el
accept.value += ','
})
props.fileType.slice(0, fileList.value.length - 2)
});
const show = () => {
visible.value = true;
}
const handleBeforeUpload = (file) => {
if (props.fileType) {
let fileExtension = "";
if (file.name.lastIndexOf(".") > -1) {
fileExtension = file.name.substring(file.name.lastIndexOf("."));
}
const isTypeOk = props.fileType.some(type => {
if (file.type.indexOf(type) > -1) return true;
return !!(fileExtension && fileExtension.indexOf(type) > -1);
});
if (!isTypeOk) {
ElMessage.error(`文件格式不正确,请上传${props.fileType.join("/")}格式文件!`)
return false;
}
}
}
const handleExceed = () => {
ElMessage.error(`只允许上传${props.limit}个文件`)
}
const handleUploadError = (err) => {
ElMessage.error("上传失败,请重试");
}
const handleUploadSuccess = (res, file) => {
ElMessage.success("上传成功");
cancel()
}
const handleDelete = (index) => {
fileList.value.slice(index, 1)
}
const getFileName = (name) => {
if (name.lastIndexOf("/") > -1) {
return name.slice(name.lastIndexOf("/") + 1).toLowerCase()
} else {
return ""
}
}
const submitUpload = () => {
if (fileList.value.length <= 0) {
return false
}
upload.value.submit();
}
const cancel = () => {
fileList.value = [];
visible.value = false
}
const handleHttpRequest = (param) => {
const formData = new FormData();
formData.append("file", param.file)
//处理上传
// uploadFormFile(formData).then((res)=>{
// param.onSuccess();
// upload.value.clearFiles();
// ElMessage.success("上传成功");
// emit("input",res.data)
// }).catch((err)=>{
// ElMessage.error("上传失败,请重试");
// param.onError();
// })
emit("input", fileList.value)
}
// 第二步:暴露方法
defineExpose({show})
</script>
<style scoped>
</style>
- 在父组件中调用它
假设我父组件交Parent.vue
<template>
<new-upload ref="fileUploadDialog" @input="getAttachList"></new-upload>
<el-button
type="primary"
plain
icon="el-icon-plus"
size="small"
@click="handleAdd"
>上传</el-button>
</template>
<script setup>
import NewUpload from "@/components/NewUpload.vue";
//定义ref
const fileUploadDialog = ref();
//调用show方法
const handleShow=()=> {
fileUploadDialog.value.show()
}
//获取子组件回调
const getAttachList=()=> {
ElMessage.success("整体成功!!!")
}
</script>
完成✌
· DeepSeek “源神”启动!「GitHub 热点速览」
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· NetPad:一个.NET开源、跨平台的C#编辑器