基于VUE和element封装upload组件

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,377评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,390评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,967评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,344评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,441评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,492评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,497评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,274评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,732评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,008评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,184评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,837评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,520评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,156评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,407评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,056评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,074评论 2 352

推荐阅读更多精彩内容

  • 1.setattr()函数[delattr()删除属性]描述:setattr函数对应函数getatt(),用于设置...
    有可能_666阅读 270评论 0 0
  • 1.授权的介绍官方如何请求数据模仿新浪微博如何请求数据2.在网页中演示打开微博开发平台,成为新浪开发者,创建应用程...
    super皮阅读 201评论 0 0
  • npm start == roadhog server roadhog webpack自动打包和热更替默认配置en...
    _贺瑞丰阅读 200评论 0 1
  • 今天晚上的播音主题是——你是谁?看似非常简单荒谬的问题,但当我们只有真正清晰了我是谁?我从哪里来?我要去向哪里? ...
    小帕_dreamer阅读 220评论 0 0
  • 可能我们都会遇到让自己尴尬的事情,比如你是学编导的,就会有人说,帮我写个剧本吧。你是学摄影的,就会有人说,帮我拍张...
    叫我黄某某阅读 789评论 7 13