基于vue elementui封装的文件上传组件

由于项目中经常使用文件上传,但是我们发现要使用的方法基本上是固定的,就那么几个,总是复制来复制去,很麻烦,尤其是当一个页面有多个上传时,代码量很大,还很乱,于是想着能不能自己封装一下,所以今天它来了,哈哈,有什么问题希望大家指点。

== 直接上代码了,不废话了==

创建组件
index.vue页面内容

<template>
    <div class="fileUploadContainer" style="margin-top:15px;">
        <div v-show="flag" class="progressContaienr">
            <el-progress
                type="circle"
                :percentage="uploadPercent"
                :color="colors"
            ></el-progress>
        </div>
        <el-upload
            v-loading="loading"
            :element-loading-text="loadingTextD"
            element-loading-spinner="el-icon-loading"
            ref="upload"
            :headers="headers"
            :action="url"
            :on-preview="handlePictureCardPreview"
            :on-remove="handleRemove"
            :file-list="fileList"
            :accept="accepted"
            :list-type="listTypeD"
            :on-exceed="handleExceed"
            :before-upload="handleBeforeUpload"
            :before-remove="beforeRemove"
            :on-progress="handleUploadProgress"
            :on-change="handleChange"
            multiple
            :auto-upload="false"
            :on-success="handleSuccess"
            :on-error="handleError"
            :limit="limit"
        >
            <!-- <i class="el-icon-plus"></i> -->
            
            <el-button slot="trigger" size="small" type="primary">{{
                btnTextD[0]
            }}</el-button>
            <el-button 
                style="margin-left: 10px;margin-top:110px"
                size="small"
                type="success"
                @click="submitUpload"
                >{{ btnTextD[1] }}</el-button
            >
            <div slot="tip" class="el-upload__tip" >
                <!-- 只能上传jpg/png文件,且不超过500kb -->
                {{ tipsD }}
            </div>
            <!-- <el-progress v-if="flag" type="circle" :percentage="uploadPercent" style="margin-top:30px;"></el-progress> -->
        </el-upload>
        <el-dialog :visible.sync="dialogVisible" title="查看" append-to-body >
            <img width="100%" :src="dialogImageUrl" alt="" />
        </el-dialog>
    </div>
</template>
<script>
// 改组件由自己封装,在以前我们用elementUI 的<el-upload> 时,总是要写很多的方法;
// 代码冗余严重,封装改组件主要是为了以后使用起来方便
// 组件使用说明
// -----------------------------参数------------------------------------
// limit: 限制文件上传个数  '3'
// fileType: 文件类型   ['xlsx','xls']
// btnText: 按钮中显示的文字内容 ['选取文件','上传']
// url: 文件上传的地址   'http://fileUpload/'
// fileSize: 文件的大小个单位   [3,'kb']或[3.'m']
// listType: 文件的展示方式    'text'  'picture' 'picture-car'
//   <fileUpload
//    @uploadSuccess="uploadSuccess"
//    :limit="1"
//    :fileSize="fileSize"
//    :fileType="fileType"
//    :btnText="btnText"
//    :listType="listType"
//    :url="address + 'torder/torderImport'"
//    />
export default {
    props: {
        limit: "",
        fileType: {
            type: Array,
            default: function() {
                return [];
            }
        },
        btnText: {
            type: Array,
            default: function() {
                return [];
            }
        },
        url: {
            type: String,
            default: ""
        },
        loadingText: {
            type: String,
            default: ''
        },
        // 数组,[大小,单位]
        fileSize: {
            type: Array,
            default: function() {
                return [];
            }
        },
        listType: {
            type: String,
            default: function() {
                return "";
            }
        },
        headers:{
            type: Object,
            default: function() {
                return {};
            }
        }
    },
    data() {
        return {
            fileList: [],
            baseUrl: process.env.BASE_API,
            dialogVisible: false,
            dialogImageUrl: "",
            listTypeD: "",
            fileSizeD: "",
            btnTextD: [],
            tipsD: "",
            accepted: "",
            loadingTextD: '',
            fileAllType: [
                "doc",
                "docx",
                "xls",
                "xlsx",
                "pdf",
                "PDF",
                "jpg",
                "JPG",
                "eml",
                "mp4"
            ],
            colors: [
                        {color: '#fff143', percentage: 10},
                        {color: '#4b5cc4', percentage: 20},
                        {color: '#ff7500', percentage: 30},
                        {color: '#ff4777', percentage: 40},
                        {color: '#3b2e7e', percentage: 50},
                        {color: '#bddd22', percentage: 60},
                        {color: '#a3d900', percentage: 70},
                        {color: '#70f3ff', percentage: 80},
                        {color: '#8d4bbb', percentage: 90},
                        {color: '#00bc12', percentage: 100}
                    ],
            uploadPercent: 0,
            flag: false,
            interval: "",
            loading: false
        };
    },
    watch: {},
    methods: {
        submitUpload() {
            this.$refs.upload.submit();
        },
        handleBeforeUpload(file) {
            const fileType = file.name
                .substring(file.name.lastIndexOf(".") + 1)
                .toLowerCase();
            let size;
            if (this.fileSize === 0) {
                size = file.size / 1024 / 1024 < 5;
            } else {
                if (
                    this.fileSize[1].toLowerCase() === "kb" ||
                    this.fileSize[1].toLowerCase() === "m"
                ) {
                    if (this.fileSize[1].toLowerCase() === "kb") {
                        size = file.size / 1024 < this.fileSize[0];
                    } else {
                        size = file.size / 1024 / 1024 < this.fileSize[0];
                    }
                } else {
                    size = false;
                }
            }
            if (this.fileType.indexOf(fileType) < 0) {
                this.$message.error("上传文件格式错误!");
                return false;
            }
            if (!size) {
                if (this.fileSize === 0) {
                    this.$message.error("上传文件大小不能超过 5M");
                } else {
                    this.$message.error(
                        "上传文件大小不能超过 " +
                            this.fileSize[0] +
                            this.fileSize[1]
                    );
                }
                return false;
            }
            return file;
        },
        // 图片移除时处理数据
        handleRemove(file, fileList) {
            // let item = [];
            // fileList.forEach(el => {
            //     item.push(el.url);
            // });
            // this.$emit('removeimg', item);
        },
        handlePictureCardPreview(file) {
            this.dialogImageUrl = file.url;
            this.dialogVisible = true;
      },
        // 判断图片数量
        handleExceed(files, fileList) {
            this.$message.warning(
                `当前限制选择 ${this.limit} 个文件,本次选择了 ${
                    files.length
                } 个文件,共选择了 ${files.length + fileList.length} 个文件`
            );
        },
        beforeRemove(file, fileList) {}, // 上传图片成功事件
        handleSuccess(response, file, fileList) {
            clearInterval(this.interval);
            this.$emit("uploadSuccess", response, file, fileList);
            this.loading = false;
            this.uploadPercent = file.percentage;
            const timeOut = setTimeout(() => {
                this.flag = false;
                this.uploadPercent = 0;
                clearTimeout(timeOut);
            },1000)
            this.$refs.upload.clearFiles();
        },
        // eslint-disable-next-line handle-callback-err
        handleError(error, file, fileList) {
            this.loading = false;
            this.flag = false;
            this.uploadPercent = 0;
            this.$message.error("失败了");
        },
        handleChange(file, fileList) {},
        handleUploadProgress(event, file, fileList) {
            if (file.status === "ready") {
                this.flag = true;
                this.loading = true;
                this.interval = setInterval(() => {
                    if (this.uploadPercent >= 99) {
                        clearInterval(this.interval);
                        return
                    }
                    this.uploadPercent += 1;
                }, 300);
            }
        }
    },
    mounted() {
        // 按钮内显示的字
        if (this.btnText.length === 0) {
            this.btnTextD = ["选取文件", "上传"];
        } else {
            this.btnTextD = this.btnText;
        }
        // 展示的方式,图片有 picture,picture-card
        if (this.listType.length !== "") {
            this.listTypeD = this.listType;
        }
        // 提示内容
        if (this.fileType.length === 0) {
            if (this.fileSize === 0) {
                this.tipsD =
                    "可以上传doc/docx/xls/xlsx/pdf/PDF/jpg/JPG/eml/mp4文件,且文件不能大于5M";
            } else {
                this.tipsD =
                    "可以上传doc/docx/xls/xlsx/pdf/PDF/jpg/JPG/eml/mp4文件,且文件不能大于" +
                    this.fileSize[0] +
                    this.fileSize[1];
            }
        } else {
            this.tipsD = "可以上传";
            if (this.fileSize === 0) {
                for (let i = 0; i < this.fileType.length; i++) {
                    if (i === this.fileType.length - 1) {
                        this.tipsD +=
                            this.fileType[i] + "文件,且文件不能大于5M";
                    } else {
                        this.tipsD += this.fileType[i] + "/";
                    }
                }
            } else {
                for (let i = 0; i < this.fileType.length; i++) {
                    if (i === this.fileType.length - 1) {
                        this.tipsD +=
                            this.fileType[i] +
                            "文件,且文件不能大于" +
                            this.fileSize[0] +
                            this.fileSize[1];
                    } else {
                        this.tipsD += this.fileType[i] + "/";
                    }
                }
            }
        }
        if (this.fileType.length !== 0) {
            for (let i = 0; i < this.fileType.length; i++) {
                if (i === this.fileType.length - 1) {
                    this.accepted += "." + this.fileType[i];
                } else {
                    this.accepted += "." + this.fileType[i] + ",";
                }
            }
        }
        if(this.loadingText == '') {
            this.loadingTextD = '处理中...'
        }else {
            this.loadingTextD = this.loadingText;
        }
    }
};
</script>
<style type="text/css" scoped>
/* .el-loading-spinner {
    top:15%!important;
    margin-top: -50px!important;
} */
</style>

这里是如何引入

import fileUpload from "@/components/fileUpload";

注册

components: {
    fileUpload
  },

定义变量

// ----------------------picture----------------------------------------
      fileSizePicture: [200, "M"],
      btnTextPicture: ["选取图片", "上传"],
      fileTypePicture: ["jpg", "png", "jpeg", "gif"],
      listTypePicture: "picture-card",
      loadingTextPicture: "上传图片中...",
      // ----------------------picture----------------------------------------

定义success方法(response调用后台上传接口返回的数据,自己做处理)

uploadSuccess(response) {
      if (response.code === 200) {
        this.msgSuccess(response.msg);
        if (this.img_file.type == "update") {
          getInvoiceFile(this.temp.id).then(response => {
            this.fileList = response.data;
            this.innerVisible = false;
          });
        }
      } else {
        this.msgError(response.msg);
      }
    },

页面内使用

<fileUpload
                @uploadSuccess="uploadSuccess"
                :limit="10"
                :headers="没有时可以不写"  
                :fileSize="fileSizePicture"
                :fileType="fileTypePicture"
                :btnText="btnTextPicture"
                :listType="listTypePicture"
                :url="你的上URL "
                :loadingText="loadingTextPicture"
              />

这样就能用了,好了,朋友喊我吃饭去了,就先不胡扯了,拜拜;

注意了 ,忘了告诉大家,进度条是假的。

Logo

前往低代码交流专区

更多推荐