基于VUE和element封装upload组件

作者: 一片空白1233 | 来源:发表于2019-07-07 16:49 被阅读2次

    工作需要,要实现图片文档的上传查看下载等功能,于是就基于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>
    
    

    相关文章

      网友评论

        本文标题:基于VUE和element封装upload组件

        本文链接:https://www.haomeiwen.com/subject/csxxbftx.html