Vue3封装一个Element的自定义上传组件

封装一个ElementPlus的自定义上传组件

写在前面,工作中要封装一个文件上传组件,想着以后肯定也能用得到,就给记录了下来
文章通篇借鉴的是这位大佬的,有需要的可以去看看
https://blog.51cto.com/u_15295608/3527047
image
直接上代码:

先看样式:

image
就是这样子了!!!,这是个弹窗的形式,有空我再整个无弹窗的

代码在此:

  1. 首先创建一个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>
  1. 在父组件中调用它
    假设我父组件交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>

完成✌

posted @   ProsperousEnding  阅读(226)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek “源神”启动!「GitHub 热点速览」
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· NetPad:一个.NET开源、跨平台的C#编辑器
  1. 1 原来你也在这里 周笔畅
  2. 2 世间美好与你环环相扣 柏松
  3. 3 起风了 吴青峰
  4. 4 极恶都市 夏日入侵企划
  5. 5 所念皆星河 CMJ
  6. 6 所念皆星河-歌词版 房东的猫
  7. 7 卡农-钢琴版 dylanf
  8. 8 The truth that you leave Pianoboy高至豪
  9. 9 虹之间 米叔啊
极恶都市 - 夏日入侵企划
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.

作词 : 王星

作曲 : 灰鸿啊/皮皮

编曲 : 夏日入侵企画

制作人 : 邢硕

节奏吉他 : 肯尼

主音吉他 : 张伟楠

贝斯 : 皮皮

鼓 : 海鑫

和声 : 邢硕

音效制作 : 邢硕

录音 : 邢硕/夏国兴

混音 : 于昊

特别鸣谢 : 张伟楠

这城市的车流和这地表的颤抖

像一颗石子落入地心之后泛起的温柔

暗涌

河水流过转角她的楼

被梦魇

轻声呓语唤醒身后的幼兽

失效感官焦灼只剩下

麻木愚钝无从感受

共同支撑全都瓦解

只是我们现在都

已忘记到底是

谁隐藏春秋

谁在大雨之后

把旗帜插在最高的楼

过去陈旧的还在坚守

内心已腐朽

摇摇欲坠不停退后

毁灭即拯救

夏日掠夺春秋

结局无法看透

眼看这情节开始变旧

所有的城池已失守

最终无法占有

无眠辗转

伴着人间破碎的旧梦

像繁星

退却后只剩下混沌的夜空

炙热

掩盖风声鹤唳的担忧

把所有失落无助反手推入

无尽的白昼

失效感官焦灼只剩下

麻木愚钝无从感受

共同支撑全都瓦解

只是我们现在都已经忘记到底是

谁隐藏春秋

谁在大雨之后

把旗帜插在最高的楼

过去的陈旧还在坚守

内心已腐朽

摇摇欲坠不停退后

毁灭即拯救

夏日掠夺春秋

结局无法看透

眼看这情节开始变旧

所有的城池早已失守

惶恐难以接受

缠绵往复不肯放手

最终无法占有

谁隐藏春秋

谁在大雨之后

把旗帜插在最高的楼

过去的陈旧还在坚守

内心已腐朽

摇摇欲坠不停退后

毁 灭 即 拯 救

谁掠夺春秋

谁在大雨之后

把旗帜插在最高的楼

过去的陈旧还在坚守

内心已腐朽

摇摇欲坠不停退后

毁灭即拯救

夏日掠夺春秋

结局无法看透

明知城池已失守

缠绵往复不肯放手

最终无法占有

点击右上角即可分享
微信分享提示