关于ElementUI的单图片上传

2,922 阅读2分钟

前言

很久没写文章了,主要还是工作太忙了。这篇文章记录一下,我在工作中遇到的问题,及解决的办法,也方便以后参考。

UI要我实现的效果图如下:

上传图片后会显示重新上传按钮,且文字位置会变,当然这很简单。

有难度的地方就是:1.这是个单文件上传;2.需要校验图片是否满足要求。

2都好解决,但也要小心处理。对于1,很多人会在el-upload组件中加上参数:limit="1",我起先也是这么尝试的,是无法上传第二张图片了,但是那个带+号的方框依旧会在,你依旧可以选择图片,只是无法上传,WTF,不能容忍,极差的体验。后面在对接后台的时候,我发现我的请求还要设置请求头headers带上Authorization_token认证的token信息及设置Content-Type字段为multipart/form-data,所以我还得走自定义请求。

实现

别人的问题有时候也是你的问题,只是你还没遇到。不多说,直接贴关键代码:

vue模板部分:

<el-form-item label="商品图片" prop="goodsPic" style="width: 150%;" class="is-required">
  <el-upload
    ref="upload"
    action
    :class="{hide: !hideUpload}"
    list-type="picture-card"
    accept="image/png, image/jpeg, image/gif"
    :auto-upload="false"
    :before-upload="beforeUpload"
    :on-change="uploadChange"
    :http-request="httpRequest"
    :file-list="fileList"
  >
    <i ref="file" slot="trigger" class="el-icon-plus" />
    <div slot="file">
      <img class="el-upload-list__item-thumbnail" :src="form.goodsPic">
      <span class="el-upload-list__item-actions">
        <span class="el-upload-list__item-preview" @click="previewVisible = true">
          <i class="el-icon-zoom-in" />
        </span>
      </span>
    </div>
  </el-upload>
  <el-button v-if="!hideUpload" @click="$refs.file.click()">重新上传</el-button>
  <span :class="{tip: hideUpload}" style="color: #C0C4CC;margin-left: 10px;">要求:1M以内,格式 jpeg、gif、png;尺寸不小于800*800px</span>
  <el-dialog :visible.sync="previewVisible" append-to-body width="740px" top="5vh">
    <img width="700px" height="700px" :src="form.goodsPic">
  </el-dialog>
</el-form-item>

JS部分:

export default {
  data() {
    return {
      form: {
        goodsPic: '',
      },
      fileList: [], // 上传的图片列表,回显时会有用
      previewVisible: false, // 图片预览弹层是否显示
      hideUpload: true, // 是否隐藏重新上传按钮
    }
  },
  created() {
    if (this.type) { // 编辑时
      this.fileList = [{ url: this.form.goodsPic }] // 回显时图片的固定格式
      this.hideUpload = false
    }
  },
  methods: {
    httpRequest(param) { // 自定义图片上传
      uploadImg(param) // 图片上传的异步方法
        .then(res => {
          this.form.goodsPic = res.data.filePath
        })
        .catch(err => {
          this.$message.error(err)
        })
    },
    uploadChange() { // 选取了图片就进行上传
      this.$refs.upload.submit()
    },
    beforeUpload(file) { // 上传了图片前的校验
      const isLt1M = file.size / 1024 / 1024 < 1
      if (!isLt1M) {
        this.$message.error('上传的图片大小不能超过 1MB!')
      }
      const isSize = new Promise(function(resolve, reject) {
        const width = 800
        const height = 800
        const _URL = window.URL || window.webkitURL
        const img = new Image()
        img.onload = function() {
          const valid = img.width >= width && img.height >= height
          valid ? resolve() : reject()
        }
        img.src = _URL.createObjectURL(file)
      }).then(() => {
        this.hideUpload = false
        if (this.$refs.upload.uploadFiles.length > 1) this.$refs.upload.uploadFiles.splice(0, 1)
        return file
      }, () => {
        this.$message.error('上传的图片尺寸应不小于800*800px')
        return Promise.reject()
      })
      return isLt1M && isSize
    }
  }
}

css部分

.hide >>>.el-upload--picture-card {
    display: none;
}

对于上传请求的封装:

export function uploadImg(data) {
  const formData = new FormData()
  formData.append('file', data.file)
  return request({
    url: '/image/upload',
    method: 'post',
    data: formData,
    headers: {
      'Content-Type': 'multipart/form-data'
    }
  })
}

解析

单图片上传,我没有添加限制参数:limit="1",而是在文件满足要求后,让上传文件的列表每次从头部减1,用的数组的splice方法,规避数组的检测更新问题。其次一定要添加on-change属性,来触发上传事件。如果要添加环形进度条,模拟组件原来的那种效果,我的想法是在el-upload上层覆盖个el-progress组件,然后在请求中设置监听文件上传进度来渲染进度条,具体的网上百度,我也没实现这个效果😂😂😂