让前端飞Web前端之路前端Vue专辑

基于VUE和element封装upload组件

2019-07-07  本文已影响2人  一片空白1233

工作需要,要实现图片文档的上传查看下载等功能,于是就基于ele的upload组件做了封装,途中爬过几次坑,给大家做一次分享,共勉之!

1、打开弹窗页面时,获取上传列表

要在页面打开时请求列表接口,获取数据(若是页面建议放在mounted里面,若是弹框建议watch参数:visible.sync==true时),请求方法如下

  // 获取列表
    findLists() {
      const tbJson = JSON.stringify({
        length: 10,
        start: 1,
        searchBy: [],
        orderBy: {}
      })
      this.$axios.post('/api/files/list', {
     //获取列表需要参数
        tbJson,
        fid: this.pId
      }).then(res => {
        if (res.status === 200) {
          this.fileList = Object.assign([], [])
          //后台返回数据需要做处理,才能正常展示
          res.data.list.forEach((l) => {
            const obj = {
              name: l.fname,
              url: process.env.VUE_APP_BASE_API + '/' + l.fpath
            }
            this.fileList.push(obj)
          })
          this.defaultfileList = Object.assign([], res.data.list)
        } else {
          this.$mess.messagePrompt(res.message, 'error', true, false)
        }
      }).catch(() => {
      })
    },

2、上传图片或者文档

上传时,需要上传地址,头信息,额外参数等信息带给后台,这些参数之类的还好ele都给封装过了,基于组件就能完成

        <el-upload
          :accept="accept"//接受上传的[文件类型]
          :action="upload"//必选参数,上传的地址
          :data="datas()"// 上传时附带的额外参数
          :headers="headers()"//    设置上传的请求头部
          :multiple="multiple"
          :on-remove="handleRemove"//文件列表移除文件时的钩子
          :on-success="handleSuccess"//文件上传成功时的钩子
          :on-preview="handlePictureCardPreview"//点击文件列表中已上传的文件时的钩子
          :disabled="disabledInput"
          list-type="picture"//文件列表的类型
          :before-remove="beforeRemove"//删除文件之前的钩子
          :file-list.sync="fileList"//上传的文件列表, 
        >
          <el-button v-if="!isRead" size="small" type="primary" icon="el-icon-upload" :plain="plain" style="float: left">
            新增附件
          </el-button>
        </el-upload>

3、删除爬坑(方法很笨,不建议学习,有好的办法多多交流)

测试发现,upload几个事件的返回值是组件处理后的数据(数据格式不是列表的数据格式)。接下来就要忙着找ID找下标来做删除.....
思路:因为uid是数据的唯一标识,渲染列表后将列表数据存起来,点击删除某一项时取其uid进行匹配,从而删除。


1562486902(1).jpg
1562487032(2).jpg

4、附上完整组件(部分是因为业务需求,可忽略....)

<template>
  <div>
    <el-dialog
      v-if="dialogVisible"
      :close-on-click-modal="false"
      :visible.sync="dialogVisible"
      width="550px"
      title="附件列表"
    >
      <div class="upload-container" style="max-height:500px;overflow-y:auto;">
        <el-dialog :close-on-click-modal="false" :visible.sync="dialogVisibleImg" :title="ImgName" append-to-body>
          <img width="100%" :src="dialogImageUrl" alt="">
        </el-dialog>
        <el-upload
          class="uploadShow"
          :accept="accept"
          :action="upload"
          :data="datas()"
          :headers="headers()"
          :multiple="multiple"
          :on-remove="handleRemove"
          :on-success="handleSuccess"
          :on-preview="handlePictureCardPreview"
          :disabled="disabledInput"
          list-type="picture"
          :before-remove="beforeRemove"
          :file-list.sync="fileList"
        >
          <el-button v-if="!isRead" size="small" type="primary" icon="el-icon-upload" :plain="plain" style="float: left">
            新增附件
          </el-button>
        </el-upload>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import dialogMixins from '@/mixins/diolog'
import { getToken } from '@/utils/auth'
export default {
  components: {
  },
  mixins: [dialogMixins],
  props: {
    multiple: {
      type: Boolean,
      default: true
    },
    isRead: {
      type: Boolean,
      default: false
    },
    disabledInput: {
      type: Boolean,
      default: false
    },
    accept: {
      type: String,
      default: ''
    },
    pId: {
      type: String,
      default: ''
    },
    plain: {
      type: Boolean,
      default: false
    }
  },

  data() {
    return {
      defaultfileList: [],
      innerfileList: [], // 删除之前数据
      fileList: [], // 删除之后数据(渲染数据)
      dialogVisibleImg: false,
      dialogImageUrl: '',
      ImgName: ''

    }
  },
  computed: {
    upload() {
      return `${process.env.VUE_APP_BASE_API}/api/files/upload`
      // return (process.env.NODE_ENV === 'production' ? process.env.BASE_URL : '/api') + '/api/files/upload'
    }
  },
  watch: {
    dialogVisible(e) {
      if (e) {
        this.findLists()
      }
    }
  },
  methods: {
    // 获取列表
    findLists() {
      const tbJson = JSON.stringify({
        length: 10,
        start: 1,
        searchBy: [],
        orderBy: {}
      })
      this.$axios.post('/api/files/list', {
        tbJson,
        fid: this.pId
      }).then(res => {
        if (res.status === 200) {
          this.fileList = Object.assign([], [])
          res.data.list.forEach((l) => {
            const obj = {
              name: l.fname,
              url: process.env.VUE_APP_BASE_API + '/' + l.fpath
            }
            this.fileList.push(obj)
          })
          this.defaultfileList = Object.assign([], res.data.list)
        } else {
          this.$mess.messagePrompt(res.message, 'error', true, false)
        }
      }).catch(() => {
      })
    },
    headers() {
      const object = {
        Authorization: getToken('token')

      }
      return object
    },
    datas() {
      const pId = {
        fid: this.pId
      }
      return pId
    },
    beforeRemove(file, fileList) {
      // 删除提醒
      return this.$mess.confirm().then(() => {
        this.innerfileList = JSON.parse(JSON.stringify(fileList))
      })
    },
    handleSuccess(res, file, fileList) {
      this.defaultfileList.push({ id: res.data })
      this.fileList = Object.assign([], fileList)
      this.innerfileList = Object.assign([], fileList)
      this.$emit('update:fileList', fileList)
    },
    handleRemove(file, fileList) {
      const index = this.innerfileList.findIndex(el => {
        return file.uid === el.uid
      })
      this.$axios.post('/api/files/del', {
        ids: this.defaultfileList[index].id
      }).then(res => {
        if (res.status === 200) {
          this.innerfileList.splice(index, 1)
          this.defaultfileList.splice(index, 1)
          this.fileList.splice(index, 1)
          this.$message({
            type: 'success',
            message: '操作成功'
          })
        } else {
          this.$mess.messagePrompt(res.message, 'error', true, false)
        }
      }).catch(() => {
      })
    },
    handlePictureCardPreview(file) {
      const arr = ['gif', 'jpg', 'jpeg', 'png', 'PNG', 'JPG', 'GIF']
      const s = arr.filter(el => {
        return file.url.includes(el)
      })
      if (s.length) {
        this.dialogImageUrl = file.url
        this.dialogVisibleImg = true
      } else {
        window.open(file.url)
      }
    }

  }
}
</script>

<style scoped>
.uploadShow{
}
</style>

上一篇下一篇

猜你喜欢

热点阅读