欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

vue+elementUi图片上传组件使用详解

程序员文章站 2022-09-06 23:39:16
上传组件封装需求分析 在基于elementui库做的商城后台管理中,需求最大的是商品管理表单这块,因为需要录入各种各样的商品图片信息。加上后台要求要传递小于2m的图片,因...

上传组件封装需求分析

在基于elementui库做的商城后台管理中,需求最大的是商品管理表单这块,因为需要录入各种各样的商品图片信息。加上后台要求要传递小于2m的图片,因此封装了一个upload.vue组件作为上传页面的子组件,它用于管理图片上传逻辑。

upload.vue解析

upload主要用于实现表单上传图片的需求,主要由input +img 构成当没有图片的时候显示默认图片,有图片则显示上传图片,因为input样式不太符合需求所以只是将起设置为不可见,不能将其设置为display:none。否则将将无法触发input的change事件

upload.vue代码如下:

<template>
 <div>
 <div class="upload-box" :style="imgstyle">
  <!-- 用户改变图片按钮的点击 触发上传图片事件 -->
  <input type="file" :ref="imgtype$1"  @change="upload(formval$1,imgtype$1)" class="upload-input" />
  <!-- img 的 src 用于渲染一个 图片路径 传入图片路径 渲染出图片 -->
  <img :src="formval$1[imgtype$1]?formval$1[imgtype$1]:'static/img/upload.jpg'" />
 </div>
 </div>
</template>
<script>
/* 
 该组件因为要上传多个属性的图片 主图(mainimg) 详细图(detailimg) 规格图 (plusimg) 
 该组件基于压缩插件lrz,所以下方打入该组件
 npm install lrz --save 即可
*/
import lrz from 'lrz';
export default {
  name: 'uploadimg', //组件名字
  props: {
    formval: {
      type: object, //props接受对象类型数据(表单对象也可以是纯对象类型)
      required: true,
      default: {}
    },
    imgtype: {        //表单对象中的图片属性 example:mainimg
      type: string,
      required: true,
      default: ''
    },
    imgstyle: {
      type: object,    // 用于显示的图片的样式 
      required: true //必须传递
    }
  },
  created: function() {
    //生命周期函数 
  },
  data: function() {
   /*
     因为该组件需要改变父组件传递过来的值,
     所以将起拷贝一份
   */
    let formval$1 = this.formval;
    let imgtype$1 = this.imgtype;
    return {
      formval$1,
      imgtype$1,
      uploadurl: url,//你的服务器url地址
    };
  },
  methods: {
    upload: function(formval, imgtype) {
      var self = this;
      //图片上传加载我们在这里加入提示,下方需要主动关闭,防止页面卡死
      var loadinginstance = this.$loading({
        text: '上传中'
      });
      var that = this.$refs[imgtype].files[0]; //文件压缩file
      //图片上传路径
      var testurl = this.uploadurl; //图片上传路径
      try {
        //lrz用法和上一个一样也是一个压缩插件来的
        lrz(that)
          .then(function(message) {
            var formdata = message.formdata; //压缩之后我们拿到相应的formdata上传
            self.$axios
              .post(testurl, formdata)
              .then(function(res) {
                console.log(res);
                if (res && res.data.iret == 0) {
                  formval[imgtype] = res.data.objdata.surl;
                  //上传成功之后清掉数据防止下次传相同图片的时候不触发change事件 
                  self.$refs[imgtype].value = '';
                  /*
                   这里因为使用elementui中的表单验证,
                   当上传图片完成之后还会提示没有上传图片
                   所以需要通知父组件清除该验证标记 
                   */
                  self.$emit('clearvalidate', imgtype);
                  self.$nexttick(() => {
                    // 以服务的方式调用的 loading 需要异步关闭
                    loadinginstance.close();
                  });
                } else {
                  throw res.data.smsg;
                }
              })
              .catch(function(err) {
                self.$nexttick(() => {
                  // 以服务的方式调用的 loading 需要异步关闭
                  loadinginstance.close();
                });
                //接口报错弹出提示
                alert(err);
              });
          })
          .catch(function(err) {
            self.$nexttick(() => {
              loadinginstance.close();
            });
          });
      } catch (e) {
        //关闭加载动画实例
        self.$nexttick(() => {
          loadinginstance.close();
        });
      }
    }
  },
  mounted: function() {},
  watch: {
    /*
    这里需要注意当父组件上传一个图片然后通过重置按钮重置的时候.
     我们需要监听一下,防止上传同一张图片上传失败
    */
    formval: {
      handle: function(newval, oldval) {
        var imgtype = this.imgtype;
        if (newval[imgtype] == '') {
          //这里使用了原生js写法当然也可以通过ref引用找到,后者更好
          document.getelementsbyclassname('upload-input')[0].value = '';
        }
      }
    }
  }
};
</script>
<style scoped>
/*
 这里是默认的设置图片的尺寸。可以通过父组件传值将其覆盖
*/
.upload-box {
  position: relative;
  height: 100px;
  width: 100px;
  overflow: hidden;
}

.upload-box img {
  width: 100%;
  height: 100%;
}

.upload-box .upload-input {
  position: absolute;
  left: 0;
  opacity: 0;
  width: 100%;
  height: 100%;
}
</style>

商品页中使用upload组件

good.vue中我们引入upload组件。并且传递相应表单对象,需上传的图片类型的属性,以及图片显示样式给子组件

good.vue核心代码:

<template>
  <el-form ref="form" :model="form" label-width="80px" label-position="top" :rules="rules">
  <!-- 无关代码略 -->
  <el-form-item label="详情图" prop="sdetailimg" ref="sdetailimg">
   <uploadimg :form-val="form" :img-type="'sdetailimg'" :img-style="detailimgstl" @clearvalidate="clearvalidate"></uploadimg>
  </el-form-item>
  <el-form-item>
   <el-row style="text-align:center;">
   <el-button type="primary" size="medium" @click.stop="submit('form')" v-if="!form.id">保存</el-button>
   <el-button type="primary" size="medium" @click.stop="submit('form')" v-else-if="form.id">修改</el-button>
   <el-button size="medium" @click.stop="resetform('form')">重置</el-button>
   </el-row>
  </el-form-item>
  </el-form>
  <!-- 略 -->
</template>
<script>
  import uploadimg from "../common/uploadimg"; //图片上传
  export default {
  name: "good", //组件名字用户缓存 
  data: function() {
   return {
   form: {
    id: null,
    //其他字段略
    sdetailimg: "" //商品详细图
   },
   detailimgstl: {
    width: "350px",
    height: "150px"
   },
   rules: {
    sdetailimg: [{
    required: true,
    message: "请填写详细图信息",
    trigger: "change"
    }],
   }
   }
  },
  methods: {
   //这里监听子组件回写的信息,用户清除上传成功之后还显示图片未上传的bug
   clearvalidate: function(imgname) {
   //清空图片上传成功提示图片没有上传的验证字段
   this.$refs[imgname].clearvalidate();
   },
   //重置表单
   resetform: function(formname) {
   this.confirm("确认重置表单", function(self) {
    self.$refs[formname].resetfields();
   })

   }
  },
  }
</script>

写在最后

关于图片上传之前我也写过一个小程序版本,总体看来pc端的图片上传相对于小程序 要复杂一点,这个封装只能满足当下单图上传的需求也有他的不足之处。当然也可以扩展为多图上传,关于多图上传的网上也有很多例子。这里不再一一赘述。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。