vue结合element实现多图上传组件

vue 结合 element 实现多图上传组件

简介

多图上传在后台管理系统中的表单和富文本中应用较多。这里实现的有多图的上传,预览,单个的删除等常用功能

主要依赖说明 (先安装,步骤略)

{
  "element-ui": "2.11.1",
  "vue": "^2.6.10",
  "vue-router": "^3.0.1"
}

正文

1.组件

src/components/MultipleUpload.vue

<template>
  <div class="upload-container">
    <el-tooltip
      class="item"
      effect="dark"
      content="上传图片"
      placement="bottom"
      :hide-after="800"
    >
      <el-button
        :style="buttonStyle"
        icon="el-icon-upload"
        size="mini"
        type="primary"
        @click="showDialog"
        >上传图片</el-button
      >
    </el-tooltip>

    <el-dialog
      title="上传图片"
      append-to-body
      width="700px"
      :visible.sync="dialogVisible"
      center
    >
      <div v-for="(item,index) in imgSrcList" :key="index" class="img-box">
        <span class="delete-image" title="点击删除">
          <i class="el-icon-delete-solid" @click="deleteImage(index)" />
        </span>
        <img v-if="item" class="img" :src="item" alt />
      </div>
      <div class="uploadImg-box">
        <input
          ref="fileElem"
          accept="image/*"
          class="img-input"
          type="file"
          multiple="multiple"
          @change="onchange"
        />
        <el-button
          class="btn"
          size="small"
          type="primary"
          @click="handleOpenFile"
          >点击上传</el-button
        >
      </div>

      <div class="btn-box">
        <el-button @click="dialogVisible = false">取 消</el-button>
        <el-button :loading="loading" type="primary" @click="handleSubmit"
          >确 定</el-button
        >
      </div>
    </el-dialog>
  </div>
</template>

<script>
  import { Loading } from "element-ui";
  import { readFile } from "@/utils/upload"; // 见下文
  import { Base64ToBlob } from "@/utils/cos"; // 见下文

  // 定义的接口根据自己项目更换
  import { uploadImage } from "@/api/upload";

  export default {
    name: "MultipleUpload",
    props: {
      // 最大上传文件的大小
      maxFileSize: {
        type: Number,
        default: 5
      },
      buttonStyle: {
       type: Object,
       default: () => ({})
     }
    },
    data() {
      return {
        dialogVisible: false,
        loading: false,
        imgSrcList: []
      };
    },
    methods: {
      // 打开文件
      handleOpenFile() {
        const input = this.$refs.fileElem;
        // 解决同一个文件不能监听的问题
        input.addEventListener(
          "click",
          function() {
            this.value = "";
          },
          false
        );
        // 点击input
        input.click();
      },

      // 显示弹窗
      showDialog() {
        this.dialogVisible = true;
        this.imgSrcList = [];
      },

      //  监听input上传
      async onchange() {
        try {
          // 文件列表
          const files = this.$refs.fileElem.files;
          // 文件所有尺寸
          const sizes = [];
          // 所有文件的base64位地址
          const allReadFile = [];
          for (let index = 0; index < files.length; index++) {
            const item = files[index];
            sizes.push(item.size);
            allReadFile.push(readFile(item));
          }
          // 获取最大尺寸检验
          const maxSize = Math.max.apply(null, sizes);
          if (maxSize > 1024 * 1024 * this.maxFileSize) {
            this.$message({
              message: `图片不得大于${this.maxFileSize}M`,
              type: "warning",
              duration: 2000
            });
            return;
          }
          // 读取所有文件为base64数据
          const base64List = await Promise.all(allReadFile);
          this.imgSrcList = [...this.imgSrcList, ...base64List];
        } catch (error) {
          console.log(error);
        }
      },

      // 确定上传
      async handleSubmit() {
        if (!this.imgSrcList.length) {
          this.$message({
            message: "请上传图片!",
            type: "error"
          });
          return;
        }
        // 添加页面loading
        const loadingInstance = Loading.service({
          fullscreen: true,
          text: "上传中..."
        });
        // 添加按钮loading
        this.loading = true;
        try {
          // 所有blob文件
          const blobFiles = [];
          // 所有上传图片请求
          const allRequest = [];
          // Base64 数据转成blob数据
          this.imgSrcList.forEach(item => {
            const blobFile = Base64ToBlob(item);
            blobFiles.push(blobFile);
          });

          // 添加请求
          blobFiles.forEach(item => {
            allRequest.push(uploadImage(item));
          });
          // 执行请求拿到结果
          const urlList = await Promise.all(allRequest);
          // 分发事件
          this.$emit("success", urlList);
        } catch (error) {
          console.log(error, error);
        }
        // 停止loading关闭弹窗
        this.loading = false;
        this.dialogVisible = false;
        loadingInstance.close();
      },

      // 删除图片
      deleteImage(index) {
        this.imgSrcList.splice(index, 1);
      }
    }
  };
</script>

<style rel="stylesheet/scss" lang="scss" scoped>
  .btn-box {
    text-align: right !important;
  }

  .img-box {
    position: relative;
    display: inline-block;
    width: 120px;
    margin-right: 10px;
    margin-bottom: 10px;
    text-align: center;
    .img {
      width: 100%;
    }
    .delete-image {
      display: none;
      .el-icon-delete-solid {
        width: 40px;
        height: 40px;
        line-height: 40px;
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        font-size: 20px;
        color: #000;
        font-weight: 900;
      }
    }

    &:hover {
      .delete-image {
        cursor: pointer;
        width: 100%;
        height: 100%;
        position: absolute;
        background-color: rgba(255, 255, 255, 0.6);
        display: inline-block;
      }
    }
  }
  .uploadImg-box {
    width: 100%;
    height: 40px;
    margin: 0 auto;
    border-radius: 6px;
    position: relative;
    margin: 20px 0;
    .img-input {
      display: none;
    }
    .btn {
      position: absolute;
      left: 50%;
      top: 50%;
      transform: translate(-50%, -50%);
    }
  }
</style>

2.使用

<template>
  <div>
    <multiple-upload @success="handleImageSuccess" />
  </div>
</template>

<script>
  import MultipleUpload from "@/components/MultipleUpload";

  export default {
    name: "AppForm",
    components: {
      MultipleUpload
    },
    methods: {
      handleImageSuccess(urlList) {
        console.log(urlList);
      }
    }
  };
</script>

3.补充 src/utils/upload.js 文件 readFile 方法

/**
 *
 * @param {file} file 源文件
 * @desc 读取图片文件为base64文件格式
 * @retutn 返回base64文件
 */
export const readFile = file => {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = e => {
      const data = e.target.result;
      resolve(data);
    };
    reader.onerror = () => {
      const err = new Error("读取图片失败");
      reject(err.message);
    };

    reader.readAsDataURL(file);
  });
};

4.补充 src/utils/cos 文件 Base64ToBlob 方法

// base64转换成file文件
export function Base64ToBlob(urlData) {
  // 去掉url的头,并转换为byte
  const bytes = window.atob(urlData.split(",")[1]);

  // 处理异常,将ascii码小于0的转换为大于0
  const ab = new ArrayBuffer(bytes.length);
  const ia = new Uint8Array(ab);
  for (let i = 0; i < bytes.length; i++) {
    ia[i] = bytes.charCodeAt(i);
  }
  return new Blob([ab], {
    type: "image/png"
  });
}

5.使用效果
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Vue.js和Element UI的帮助下,实现多图上传也非常简单。我们可以使用`el-upload`组件实现多图上传功能。 HTML代码: ```html <template> <el-upload class="upload-demo" ref="upload" :action="uploadUrl" :multiple="true" :on-success="handleUploadSuccess" :on-error="handleUploadError" :limit="limit"> <el-button size="small" type="primary">点击上传</el-button> </el-upload> </template> ``` 在这个例子中,我们使用了`el-upload`组件实现多图上传功能。`multiple`属性设置为`true`,表示允许上传多个文件。`action`属性指定上传图片的URL,`on-success`和`on-error`属性分别指定上传成功和上传失败的回调函数。`limit`属性用于指定上传文件的最大数量。在点击上传按钮后,用户可以选择多个文件进行上传。 JavaScript代码: ```javascript <script> export default { data() { return { uploadUrl: '/upload', limit: 5, fileList: [] }; }, methods: { handleUploadSuccess(response, file) { this.fileList.push({ name: file.name, url: response.url }); this.$message.success('上传成功'); }, handleUploadError(error, file, fileList) { this.$message.error('上传失败'); } } }; </script> ``` 在这个例子中,我们定义了两个回调函数`handleUploadSuccess`和`handleUploadError`,分别用于处理上传成功和上传失败的情况。在`handleUploadSuccess`函数中,我们将上传成功的图片的名称和路径添加到`fileList`数组中,以便后续使用。在`handleUploadError`函数中,我们使用`$message`组件来提示用户上传失败的信息。 需要注意的是,我们还需要在服务器端实现图片上传的逻辑。具体实现方式可以参考前面提到的PHP和Python代码示例。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xiaofei0627

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值