前言:

vue的element框架的上传功能来封装一个上传图片的插件,支持点击和拖拽。

实现效果1:通过  showFileList  来控制,false是第一种效果,true是第二种,需要使用v-view这个图片查看插件

elementui上传图片限制图片宽高 element图片上传组件_Boo

实现效果2:

elementui上传图片限制图片宽高 element图片上传组件_element_02

实现步骤:

一、先引入相关文件一共两个,一个是uploadImg.vue ,一个是imgView.vue

1、uploadImg.vue

<template>
  <div class="uploadImgBody" v-if="Refresh">
      <!--展示已上传图片部分-->
      <imgView v-if="!showFileList" class="imgViewDiv" :imageList="fileList" @deleteImg="deleteImg"></imgView>
      <!--上传图片部分-->
      <el-upload
        v-if="isEdit"
        class="upload-image"
        ref="upload"
        :action="action"
        :headers="headers"
        :multiple="multiple"
        :data="data"
        :name="name"
        :with-credentials="cookieOK"
        :show-file-list="showFileList"
        :drag="drag"
        :accept="accept"
        :list-type="listType"
        :auto-upload="autoUpload"
        :file-list="fileList"
        :disabled="is_disabled"

        :on-preview="handlePreview"
        :on-remove="handleRemove"
        :on-success="handleSuccess"
        :on-error="handleError"
        :on-progress="handleProgress"
        :on-exceed="handleExceed"
        :on-change="onChange"

        :before-upload="beforeUpload"
        :before-remove="beforeRemove"
        :http-request="httpRequest"
      >
        <div slot="default" class="uploadImgDiv">
          <i class="el-icon-plus"></i>
          <!--提示信息-->
          <div slot="tip" class="el-upload__tip" v-if="tip_text!=''">{{tip_text}}</div>
        </div>

        <!--弹框展示上传以后的图片-->
        <div slot="file" slot-scope="{file}">
            <img
              class="el-upload-list__item-thumbnail"
              :src="file.url" alt=""
            >
            <span class="el-upload-list__item-actions">
              <span
                class="el-upload-list__item-preview"
                @click="handlePictureCardPreview(file)"
              >
                <i class="el-icon-zoom-in"></i>
              </span>
              <span
                v-if="!disabled"
                class="el-upload-list__item-delete"
                @click="handleRemove(file)"
              >
                <i class="el-icon-delete"></i>
              </span>
            </span>

        </div>

      </el-upload>
      <el-dialog :visible.sync="dialogVisible">
        <img width="100%" :src="dialogImageUrl" alt="">
      </el-dialog>
  </div>

</template>

<script>
  import imgView from './imgView'
  //element的上传文件组件
  export default {
    props:{
      /**
       * 自动上传参数
       * */
      autoUpload:{ // 是否需要选取完自动上传功能
        type: Boolean,
        default: false
      },
      action:{//上传的地址
        type: String,
        default: ''
      },
      headers: {//设置上传的请求头部
        type:Object,
        default: () => {
          return {}
        }
      },
      data: {//上传时额外带的参数
        type:Object,
        default: () => {
          return {}
        }
      },
      name:{//上传的文件字段名
        type: String,
        default: 'file'
      },
      cookieOK:{//支持发送 cookie 凭证信息
        type: Boolean,
        default: true
      },
      /**
       * 公共参数
       * */
      showFileList:{//是否显示已上传文件列表
        type: Boolean,
        default: false
      },
      drag:{//是否启用拖拽上传
        type: Boolean,
        default: true
      },
      accept:{//接受文件类型-图片上传类型-不同的格式之间以逗号隔开
        type: String,
        // default:'.doc,.docx,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document'
        default: '.jpg,.jpeg,.png'
      },
      listType:{ // 文件列表的类型 - text/picture/picture-card
        type: String,
        default: 'picture-card'
      },
      fileList:{//已上传的文件列表,
        type:Array,
        default: () => {
          // { 默认格式
          //   name: 'food.jpeg',
          //   url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'
          // }
          return [
            {
              name: 'food.jpeg',
              url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'
            }
          ]
        }
      },
      is_disabled:{//是否禁止,true是禁止,false不禁止
        type: Boolean,
        default: false
      },
      multiple:{//是否可以多选
        type: Boolean,
        default: true
      },
      limit:{//最大允许上传个数
        type: Number,
        default: 30
      },

      tip_text:{//提示信息
        type: String,
        default: ''
      },
      /**
       * 手动上传参数
       * */
      needFromUpload:{ // form表单,将上传的file文件通过 formUpload  方法发送出去
        type: Boolean,
        default: false
      },
      isEdit:{ //是否可编辑
        type: Boolean,
        default: true
      },


    },
    watch: {},
    data() {
      return {
        Refresh:true,//强制刷新
        dialogImageUrl: '',
        dialogVisible: false,
        disabled: false,
      }
    },
    created() {
    },
    mounted() {
    },
    methods: {
      /**
       * 上传-默认事件
       * */
      //文件列表移除文件时的钩子
      handleRemove(file, fileList) {
        console.log('当前移除的是:');
        console.log(file);
      },
      //点击文件列表中已上传的文件时的钩子
      handlePreview(file) {
        console.log('当前点击的是'+file);
      },
      //文件上传成功时的钩子
      handleSuccess(response, file, fileList) {
        console.log('文件上传成功');
      },
      //文件上传失败时的钩子
      handleError(err, file, fileList) {
        console.log('文件上传失败');
      },
      //文件上传时的钩子
      handleProgress(event, file, fileList) {
        console.log(file);
      },
      //文件超出个数限制时的钩子
      handleExceed(files, fileList) {
        console.log('文件超出个数限制');
      },
      //覆盖默认的上传行为,可以自定义上传的实现
      httpRequest(){

      },
      //删除文件之前的钩子,参数为上传的文件和文件列表,若返回 false 或者返回 Promise 且被 reject,则停止删除。
      beforeRemove(file, fileList) {
        console.log('当前删除的文件'+file);
        this.fileList.forEach((item,index)=>{
          if(item == file){
            this.fileList.splice(index,1)
          }
        })
      },

      /**
       * 文件状态改变时的钩子,添加文件、上传成功和上传失败时都会被调用
       */
      onChange(file, fileList) {
        this.fileList = fileList;
        console.log('当前的选中文件:');
        console.log(fileList);
      },
      /**
       * 上传文件之前的钩子,参数为上传的文件,若返回 false 或者返回 Promise 且被 reject,则停止上传。
       */
      beforeUpload(file) {
        console.log(file);
      },
      /**
       * 上传-自定义事件
       * */
      submitUpload() {
        this.$refs.upload.submit();
      },
      //清空已上传的文件列表(该方法不支持在 before-upload 中调用)
      clearFiles(){
        this.$refs.upload.clearFiles();
        this.fileList = [];
      },
      //取消上传某个文件
      abortFiles(file){
        this.$refs.upload.abort(file);
      },



      /**
       * 手动上传点击确认
       * */
      submitUploadSD(){
        let arr = this.fileList;
        let str = {
          fileList:arr
        }
        this.$emit('uploadFile',str);
      },

      /**
       * 手动刷新上传组件
       * */
      RefreshUpload(){
        let arr = this.fileList;
        this.Refresh = false;
        this.$nextTick(()=>{
          this.Refresh = true;
        })
      },

      /**
       * 打开查看图片的弹框
       * */
      handlePictureCardPreview(file) {
        this.dialogImageUrl = file.url;
        this.dialogVisible = true;
      },
      //删除当前图片
      deleteImg(item){
        let uid = item.other.uid;
        this.fileList.forEach((item,index)=>{
          if(item.uid == uid){
            this.fileList.splice(index,1)
          }
        })
      }


    },
    components: {
      imgView
    },
    beforeDestroy() {
    }

  }
</script>

<style lang='scss' scoped>
  .uploadImgBody{
    .imgViewDiv{
      display: inline-block;
      vertical-align: top;
    }
    .upload-image{
      display: inline-block;
    }
  }
  .upload-image{
    div{
      width:100%;
      height: 100%;
    }
  }
</style>

2、imgView.vue ,这个插件主要是基于  v-viewer 的封装,如果npm 下载的有问题,无法使用,请点我

<template>
    <viewer :images="images">
        <div class="imgDiv" v-for="(item,index) in images" :key="'img'+index" @mouseover="mouseOver(index)"  @mouseleave="mouseLeave(index)">
          <img :src="item.src" :key="item.index" width="148" height="148" style="margin-right:10px;">
          <p class="iconStyle" v-if="item.show" @click="deleteImg(item)">
            <i class="el-icon-close"></i>
          </p>

        </div>

    </viewer>
</template>


<script>
  import Vue from 'vue';
  import Viewer from 'v-viewer'
  import 'viewerjs/dist/viewer.css'
  Vue.use(Viewer);
  Viewer.setDefaults({
      'inline':false,//启用 inline 模式
      'button':true, //右上角按钮
      "navbar": true, //底部缩略图
      "title": true, //当前图片标题
      "toolbar": true, //底部工具栏
      "tooltip": true, //显示缩放百分比
      "movable": true, //是否可以移动
      "zoomable": true, //是否可以缩放
      "rotatable": true, //是否可旋转
      "scalable": true, //是否可翻转
      "transition": true, //使用 CSS3 过度
      "fullscreen": true, //播放时是否全屏
      "keyboard": true, //是否支持键盘
      "url": "data-source",
      ready: function (e) {
        console.log(e.type,'组件以初始化');
      },
      show: function (e) {
        console.log(e.type,'图片显示开始');
      },
      shown: function (e) {
        console.log(e.type,'图片显示结束');
      },
      hide: function (e) {
        console.log(e.type,'图片隐藏完成');
      },
      hidden: function (e) {
        console.log(e.type,'图片隐藏结束');
      },
      view: function (e) {
        console.log(e.type,'视图开始');
      },
      viewed: function (e) {
        console.log(e.type,'视图结束');
      },
      zoom: function (e) {
        console.log(e.type,'图片缩放开始');
      },
      zoomed: function (e) {
        console.log(e.type,'图片缩放结束');
      }
    });

export default {
  props: {
    imageList:Array | Object,//预览传进来的图片地址,这里因为项目中已经定型了,所以传一个string进来,然后手动转 array
  },
  watch: {
    //传来的图片地址
    imageList(val){
      let type = Array.isArray(val);
      if(!type){
        this.changeArr(val.url);
      }else{
        this.changeArrT(val);
      }
    },
  },
  data () {
    return {
      isShow:false,//是否展示预览弹框
      images:[
          // {src:'https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=3272199364,3404297250&fm=26&gp=0.jpg',index:1},
          // {src:'https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=3267295166,2381808815&fm=26&gp=0.jpg',index:2},
          // {src:'https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=3429654663,2972188411&fm=26&gp=0.jpg',index:3},
          // {src:'https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=3597323878,2962972725&fm=26&gp=0.jpg',index:4},
        ]
    };
  },

  components: {},

  computed: {},

  created() {},

  mounted() {
    let type = Array.isArray(this.imageList);
    if(!type){
      this.changeArr(this.imageList.url);
    }else{
      this.changeArrT(this.imageList);
    }
  },

  methods: {
    /**转格式 */
    changeArr(str){
      if(str.url == undefined){
        return;
      }
      let obj = {
        src : str.url,
        index : 1,
        show:false,
        other:str,
      }
      let arr = [];
          arr.push(obj);
      this.images = arr;
    },
    /**转格式 */
    changeArrT(arr){
      if(arr.length == 0){
        this.images=[];
        return;
      }
      let new_arr = [];
      arr.forEach((item,index)=>{
        let obj = {
          other:item,
          src : item.url,
          index : index,
          show:false
        }
        new_arr.push(obj);
      })

      this.images = new_arr;
    },
    //划入
    mouseOver(index){
      this.images[index].show = true;
    },
    //划出
    mouseLeave(index){
      this.images[index].show = false;
    },
    /**
     * 删除
     * */
    deleteImg(item){
      this.$emit('deleteImg',item);
    },
  },


}

</script>
<style lang='scss' scoped>
  .imgDiv{
    display: inline-block;
    position: relative;
  }
  .iconStyle{
    position: absolute;
    right: 10px;
    top: 0;
    width: 30px;
    height: 30px;
    font-size: 25px;
    text-align: center;
    background: rgba(0,0,0,.7);
    color: #fff;
  }
</style>

二、调用方法

template:

<uploadImg></uploadImg>

js:

import uploadImg from '@/components/zdy_com/upload/uploadImg'


components: {
      uploadImg
    },

到此就结束了!