【sgUploadImage】自定义组件:基于elementUI的el-upload封装的上传图片、相片组件,适用于上传缩略图、文章封面

sgUploadImage源码

html 复制代码
<template>
  <div :class="$options.name">
    <ul class="uploadImages">
      <li
        class="uploadImage"
        v-loading="loadings[i]"
        v-for="(a, i) in uploadImages"
        :key="i"
        @click="clickFile(a)"
      >
        <img :src="a" @load="load(a, i)" v-if="typeof a !== 'number'" />
        <el-button
          v-if="showRemoveBtn(a)"
          class="remove-btn"
          type="text"
          icon="el-icon-delete"
          @click.stop="remove(a, i)"
        />
      </li>
    </ul>
    <el-alert
      v-if="alertMsg !== false"
      style="margin-top: 10px"
      :closable="true"
      :close-text="``"
      :description="``"
      :effect="'light'"
      :show-icon="true"
      :title="alertMsg || `最多可上传${limit}个图片,每个附件大小不超过${maxSize}M`"
      :type="'warning'"
    />
    <el-upload
      style="display: none"
      ref="upload"
      :accept="accept"
      :action="'#'"
      :auto-upload="false"
      :multiple="true"
      :on-change="change"
      :show-file-list="false"
    />
    <el-image ref="image" style="display: none" src="" :preview-src-list="[previewSrc]" />
  </div>
</template>
<script>
export default {
  name: "sgUploadImage",
  components: {},
  data() {
    return {
      accept: `.${this.$global.resourceTypes
        .find((v) => v.label == `图片`)
        .suffixs.join(",.")}`,
      form: {},
      uploadBtn: null, //上传触发按钮
      disabled: false,
      alertMsg: ``, //如果为false就隐藏提示内容
      limit: 1, //默认只能传1张
      maxSize: 10, //默认最大传10MB的图片
      imgFiles: [], //图像的base64对象数组
      files: [], //图像的File对象数组
      previewSrc: null,
      loadings: [],
    };
  },
  props: ["data"],
  computed: {
    uploadImages() {
      return this.imgFiles && this.imgFiles.length ? this.imgFiles : 1;
    },
  },
  watch: {
    data: {
      handler(newValue, oldValue) {
        //console.log(`深度监听${this.$options.name}:`, newValue, oldValue);
        if (Object.keys(newValue || {}).length) {
          this.form = JSON.parse(JSON.stringify(newValue));
        } else {
          this.form = {};
        }
        this.disabled = this.form.disabled;
        this.alertMsg = this.form.alertMsg;
        // 获取外部回显上传列表----------------------------------------
        let files =
          typeof this.form.files === `string`
            ? JSON.parse(this.form.files || "[]")
            : this.form.files || [];
        Array.isArray(files) || (files = [files]);
        this.files = files;
        this.imgFiles = [];
        this.files.forEach((v, i) => this.getImageSrc(v, i));
        // ----------------------------------------
        this.form.accept && (this.accept = this.form.accept);
        this.form.limit && (this.limit = this.form.limit);
        this.form.maxSize && (this.maxSize = this.form.maxSize);
        this.$nextTick(() => {
          let width = this.form.width || 200;
          let height = this.form.height || 150;
          this.$el.style.setProperty("--uploadImage_width", `${width}px`);
          this.$el.style.setProperty("--uploadImage_height", `${height}px`);
          this.$el.style.setProperty(
            "--background",
            `url(http://via.placeholder.com/${width}x${height})`
          );
          this.uploadBtn = this.$refs.upload.$children[0].$refs.input;
          this.uploadBtn.webkitdirectory = this.form.webkitdirectory; //让el-upload支持上传文件夹
        });
      },
      deep: true, //深度监听
      immediate: true, //立即执行
    },
  },
  created() {},
  mounted() {},
  destroyed() {},
  methods: {
    load(d, idx) {
      this.$set(this.loadings, idx, false);
    },
    getImageSrc(file, idx = this.files.length - 1) {
      this.$set(this.loadings, idx, true);
      if (file.path) {
        this.imgFiles.push(this.$d.responseFile(file));
      } else {
        this.$g.file2Base64Image(file, (d) => this.imgFiles.push(d));
      }
    },
    showRemoveBtn(d) {
      return !(typeof d === "number");
    },
    remove(d, i) {
      this.files.splice(i, 1);
      this.imgFiles.splice(i, 1);
      this.$emit(`change`, { files: this.files });
    },

    showImage(previewSrc) {
      this.previewSrc = previewSrc;
      this.$refs.image.showViewer = true; //显示大图
    },
    clickFile(d) {
      if (this.disabled) return;
      if (typeof d === "number") {
        this.uploadBtn.click();
      } else {
        this.showImage(d);
      }
    },
    change(file) {
      if (this.files.length >= this.limit) {
        this.$message(`最多只能上传${this.limit}个文件`);
      } else {
        let fileSizeMB = file.size / 1024 / 1024; //转换文件大小(单位MB)
        if (this.maxSize && fileSizeMB > this.maxSize) {
          this.$message(
            `"${file.name}"文件大小超过${this.$g.getSize(this.maxSize * 1024 * 1024)}`
          );
        } else {
          this.files.push(file.raw);
          this.getImageSrc(file.raw);
          this.$emit(`change`, { files: this.files });
        }
      }
    },
  },
};
</script>
<style lang="scss" scoped>
.sgUploadImage {
  .uploadImages {
    display: flex;
    flex-wrap: wrap;
    align-content: flex-start;
    .uploadImage {
      flex-shrink: 0;
      margin-right: 10px;
      margin-bottom: 10px;
      position: relative;
      border-radius: 4px;
      width: var(--uploadImage_width);
      height: var(--uploadImage_height);
      /*背景图片*/
      background: #f5f7fa var(--background) no-repeat center / cover;
      img {
        width: 100%;
        height: 100%;
        object-position: center;
        object-fit: cover;
      }
      &:last-of-type {
        margin-bottom: 0;
      }
      &:hover {
        .remove-btn {
          opacity: 1;
          pointer-events: auto;
        }
      }
      .remove-btn {
        background-color: #f56c6c;
        border-radius: 88px;
        box-sizing: border-box;
        padding: 5px;
        color: white;
        cursor: pointer;
        transition: 0.2s;
        position: absolute;
        right: 10px;
        top: 10px;
        opacity: 0;
        pointer-events: none;
        &:hover {
          background-color: red;
        }
      }
    }
  }
}
</style>

应用

html 复制代码
<sgUploadImage @change="getUploadFiles" />


...


getUploadFiles({ files }) {
    console.log(`获取上传文件:`, files);
},

基于基础的el-upload组件使用【实用的代码片段】基于elementUI的el-upload的上传文件对象获取代码片段,支持上传单个、多个File或文件夹(可以获取文件夹下钻子文件夹递归文件)-CSDN博客文章浏览阅读133次,点赞5次,收藏2次。文章浏览阅读192次。【代码】【sgUploadList】自定义组件:基于elementUI的el-upload封装的上传列表组件,适用于上传附件时。【sgUploadList】自定义组件:基于elementUI的el-upload封装的上传列表组件,适用于上传附件时-CSDN博客。https://blog.csdn.net/qq_37860634/article/details/144338242

相关推荐
执键行天涯几秒前
element-plus中的resetFields()方法
前端·javascript·vue.js
一个努力学习的小男孩2 分钟前
【自学】Vues基础
vue.js
喵喵酱仔__7 分钟前
vue 给div增加title属性
前端·javascript·vue.js
m0_7482487737 分钟前
前端vue使用onlyoffice控件实现word在线编辑、预览(仅列出前端部分需要做的工作,不包含后端部分)
前端·vue.js·word
customer081 小时前
【开源免费】基于SpringBoot+Vue.JS加油站管理系统(JAVA毕业设计)
java·vue.js·spring boot·后端·spring cloud·java-ee·maven
疯狂的沙粒1 小时前
JavaScript 单例模式的创建与应用
开发语言·前端·javascript·vue.js
han_2 小时前
面试官:Vue的scoped原理是什么?
前端·vue.js·面试
Jiaberrr4 小时前
微信小程序中 crypto-js 加解密全攻略
前端·javascript·vue.js·微信小程序·小程序
一朵好运莲7 小时前
HBuilderX(uni-app)Vue3路由传参和接收路由参数!!
前端·vue.js·uni-app
qq_10613834577 小时前
快速搭建SpringBoot3+Vue3+ElementPlus管理系统
java·vue.js·spring boot·idea