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 @ 2024-12-23 15:34  ProsperousEnding  阅读(519)  评论(0)    收藏  举报