美文网首页Vue
【ant Vue】upload组件二次封装

【ant Vue】upload组件二次封装

作者: somliy | 来源:发表于2020-03-02 22:50 被阅读0次

今天使用upload组件总是回显有问题,不是回显有问题,就是上传不上去,总结了一下,写了个组件,以后就不会出现类似问题了

遇到的问题及解决方案

  1. upload组件上传回调只有一次uploading状态回调(正常是三次)

解决方案

image.png

官网中确实说明有三种回调,uploading(上传中)、done(完成)、error(错误),可是为什么只有一次呢,后来发现:如果修改回返回值fileList,他只会有一次回调(只有uploading),猜测是这个状态需要返回给组件,才能进行下一步(done)

  1. 列表中文件回显时,会只显示第一次打开的内容(回显问题)

解决方案

image.png

原因在与这两个api,分别说明:
defaultFileList:使用这个的时候,只会显示第一次传入的内容,因为组件第二次加载就不会触发了,如果数据改变也不会引起页面的变化

fileList: 这是一个受控的组件,他可以根据传入数据改变页面,所以这里我们只用fileList

  1. 文件的校验,包括大小,格式

解决方案

一开始只返回true,false,但是总是不起作用,后来试了一下promise就可以了...

组件示例,分为文件和图片

文件

<!--------------------使用方法--start-->
<b-upload
  :defaultFileList="defaultFileList"
  @change="handleChange"
/>
handleChange (data) {
  this.defaultFileList = data
},
<!--------------------使用方法--end-->

<template>
  <a-upload
    :action="actionUrl"
    :beforeUpload="beforeFileUpload"
    :disabled="disabled"
    :fileList="fileList"
    :headers="headers"
    :multiple="multiple"
    @change="handleChange"
  >
    <a-button>
      <a-icon type="upload"/>
      上传
    </a-button>
  </a-upload>

</template>

<script>

export default {
  name: 'BUpload',
  props: {
    defaultFileList: {
      type: Array,
      default: function () {
        return []
      },
      required: true
    },
    fileTypeList: {
      type: Array,
      default: function () {
        return []
      },
      required: false
    },
    limitSize: {
      type: Number,
      default: 2,
      required: false
    },
    actionUrl: {
      type: String,
      default: '/api/storage/upload',
      required: false
    },
    multiple: {
      type: Boolean,
      default: false,
      required: false
    },
    disabled: {
      type: Boolean,
      default: false,
      required: false
    }
  },
  watch: {
    defaultFileList (newVal) {
      this.fileList = newVal
    }
  },
  data () {
    return {
      headers: {
        authorization: ''
      },
      fileList: []
    }
  },
  created () {
    this.fileList = this.defaultFileList
    this.headers.authorization = 'Bearer ' + this.$store.state.user.token
  },
  methods: {
    // ---------------------------------------------file--start
    handleChange (info) {
      if (info.file.status === 'done') {
        this.$message.success('文件上传成功!')
      }
      let fileList = [...info.fileList]
      fileList = fileList.map(file => {
        if (file.response) {
          const res = file.response.data
          file.name = res.filename
          file.url = res.url
        }
        return file
      })
      this.fileList = fileList
      this.$emit('change', this.fileList)
    },
    beforeFileUpload (file) {
      return new Promise((resolve, reject) => {
        if (!this.fileTypeList) {
          const index = this.fileTypeList.indexOf(file.type)
          if (index > 0) {
            this.$message.error(`您只能上传${this.fileTypeList[index]}文件`)
          }
        }
        const limitSize = file.size / 1024 / 1024 < this.limitSize
        if (!limitSize) {
          this.$message.error(`文件大小不能大于${this.limitSize}MB`)
          return reject(new Error(`文件大小不能大于${this.limitSize}MB`))
        }
        this.$message.info('文件正在上传中...')
        return resolve(true)
      })
    }
    // ---------------------------------------------file--end
  }
}
</script>

<style scoped>

</style>

图片

<!--------------------使用方法--start-->
 <b-upload-image
  :defaultImageList="defaultImageList"
  :disabled="false"
  :multiple="true"
  @change="handleImageChange"
/>
handleImageChange (data) {
  this.defaultImageList = data
},
<!--------------------使用方法--end-->
<template>
  <div>
    <a-upload
      :action="actionUrl"
      :beforeUpload="beforeImageUpload"
      :disabled="disabled"
      :fileList="imageList"
      :headers="headers"
      :multiple="multiple"
      @change="handleImageChange"
      @preview="handleImagePreview"
      listType="picture-card"
    >
      <div v-if="defaultImageList.length < limitNum">
        <a-icon :type="imageLoading ? 'loading' : 'plus'"/>
        <div class="ant-upload-text">上传</div>
      </div>
    </a-upload>
    <a-modal :footer="null" :visible="previewVisible" @cancel="handleImageCancel">
      <img :src="previewImage" alt="example" style="width: 100%"/>
    </a-modal>
  </div>
</template>

<script>

export default {
  name: 'BUploadImage',
  props: {
    defaultImageList: {
      type: Array,
      default: function () {
        return []
      },
      required: true
    },
    fileTypeList: {
      type: Array,
      default: function () {
        return []
      },
      required: false
    },
    limitSize: {
      type: Number,
      default: 2,
      required: false
    },
    limitNum: {
      type: Number,
      default: 3,
      required: false
    },
    actionUrl: {
      type: String,
      default: '/api/storage/upload',
      required: false
    },
    multiple: {
      type: Boolean,
      default: false,
      required: false
    },
    disabled: {
      type: Boolean,
      default: false,
      required: false
    }
  },
  watch: {
    defaultImageList (newVal) {
      this.imageList = newVal
    }
  },
  data () {
    return {
      headers: {
        authorization: ''
      },
      imageLoading: false,
      previewVisible: false,
      previewImage: '',
      imageList: []
    }
  },
  created () {
    this.imageList = this.defaultImageList
    this.headers.authorization = 'Bearer ' + this.$store.state.user.token
  },
  methods: {
    // ---------------------------------------------img--start
    handleImageChange (info) {
      if (info.file.status === 'done') {
        this.$message.success('文件上传成功!')
      }
      let fileList = [...info.fileList]
      fileList = fileList.map(file => {
        if (file.response) {
          const res = file.response.data
          file.name = res.filename
          file.url = res.url
        }
        return file
      })
      this.imageList = fileList
      this.$emit('change', this.imageList)
    },
    beforeImageUpload (file) {
      return new Promise((resolve, reject) => {
        if (!this.fileTypeList) {
          const index = this.fileTypeList.indexOf(file.type)
          if (index > 0) {
            this.$message.error(`您只能上传${this.fileTypeList[index]}文件`)
          }
        }
        const limitSize = file.size / 1024 / 1024 < this.limitSize
        if (!limitSize) {
          this.$message.error(`文件大小不能大于${this.limitSize}MB`)
          return reject(new Error(`文件大小不能大于${this.limitSize}MB`))
        }
        this.$message.info('文件正在上传中...')
        return resolve(true)
      })
    },
    handleImagePreview (file) {
      this.previewImage = file.url || file.thumbUrl
      this.previewVisible = true
    },
    handleImageCancel () {
      this.previewVisible = false
    }
    // ---------------------------------------------img--end
  }
}
</script>

<style scoped>

</style>

相关文章