【求助】element的upload组件封装后,多图上传与删除时会闪动,该如何解决?

image
演示效果图:上传或删除时会有个闪动的效果,不知道怎么修复

elemnet的upload组件封装如下:

<template>
  <div>
    <el-upload
      :action="action"
      ref="upload"
      list-type="picture-card"
      accept="image/*"
      :class="{hide:WhetherUpload||isShowUpload}"
      :limit="imgLimit"
      :file-list="fileList"
      :multiple="isMultiple"
      :on-success="handleAvatarSuccess"
      :before-upload="beforeAvatarUpload"
      :on-exceed="handleExceed"
      :on-error="imgUploadError"
    >
      <i class="el-icon-plus"></i>
      <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="removeIco" class="el-upload-list__item-delete" @click="handleRemove(file,fileList)" >
            <i class="el-icon-delete"></i>
          </span>
        </span>
      </div>
    </el-upload>
    <el-dialog :visible.sync="dialogVisible" append-to-body>
      <img width="100%" :src="dialogImageUrl" alt="">
    </el-dialog>
  </div>
</template>
<script>
export default {
  name: 'upload',
  //子组件通过 props方法获取父组件传递过来的值
  props: {
    action:{type:String},//action请求地址
    imgWidth:{type:Number},//图片宽
    imgHeight:{type:Number},//图片高
    imgLimit:{type:Number,default: 1},//设置上传数量
    fileSize:{type:Number,default: 2},//设置图片大小
    fileListStr:'',//查看已上传图片
    removeIco:{type:Boolean,default:true},//是否显示删除按钮
    operationType:{type:Boolean,default:true},//刷新页面
    isShowUpload:{type:Boolean,default:false},//是否显示上传操作
  },
  data() {
     return {
       dialogImageUrl: '',
       dialogVisible: false,
       isMultiple: true,
       imgList:[],
       WhetherUpload:false,//是否显示上传操作
       fileList:[]
     }
  }, 
  watch:{
  // 已上传图片
     'fileListStr':function(){
       this.fileList=this.imageConversion(this.imgLimit,this.fileListStr);
       this.isShow()
     },
     'operationType':function(){
       this.WhetherUpload = this.fileList.length >= this.imgLimit;
     }
   }, // 创建完毕状态(里面是操作)
  created() {
     this.fileList=this.imageConversion(this.imgLimit,this.fileListStr);
     this.isShow()
   },
   /**
    * 里面的方法只有被调用才会执行
    */
  methods: {
   // 上传文件数量达标,就隐藏上传按钮
    isShow(){
      this.WhetherUpload = this.fileList.length >= this.imgLimit;
    }, // 处理上传结果
    handleImage(){
      var imgLimit = this.imgLimit //上传的最大图片数
      var imgList = []
      var fileList = this.fileList
      // 多图上传
      if(imgLimit > 1){
        if(fileList.length >= 1){
          for (let i = 0; i < fileList.length; i++) {
            if (fileList[i].response) {
              imgList.push(fileList[i].response.path);
            } else {
              imgList.push(fileList[i].url);
            }
          } 
          return imgList
        }else{
          return imgList
        }
      } // 单图上传
      else{
        if(fileList.length > 0){
          return fileList[0].response.path
        }else{
          return ''
        }
      }
    }, //移除图片
    handleRemove(file, fileList) {
      var _this = this
      if(file.response == '' || file.response == 'null'){
        var url = file.url
      }else{
        var url = file.response.path
      }
      var postData = {
        url: url,
      }
      this.$post("/attachment/delete", postData ).then((res) => {
        if (res.status == 1) {
        // 提示
          _this.$message({
            type: "success",
            message: res.msg,
          })
        } else {
         // 提示
         _this.$message.error(res.msg)
        }
      })
      for (let index = 0; index < fileList.length; index++) {
        if(fileList[index].uid==file.uid){
          this.fileList.splice(index,1) //移除数组中要删除的图片
        }
      }
      if(this.fileList == '' || this.fileList == 'null'){
        this.fileList = []
      }
      this.isShow()
      this.$emit('getImgList',this.handleImage());
    }, //预览图片时调用
    handlePictureCardPreview(file) {
      this.dialogImageUrl = file.url;
      this.dialogVisible = true;
    }, //文件上传之前调用做一些拦截限制
    beforeAvatarUpload(file) {
    // 验证上传图片格式
      const isPNG = file.type === "image/png"
      const isJPEG = file.type === "image/jpeg"
      const isJPG = file.type === "image/jpg"
      if (!isPNG && !isJPEG && !isJPG) {
        this.$message.error("上传图片只能是 jpg、png、jpeg 格式!")
        return false
      }
      // 验证上传文件大小
      const isLt2M = file.size / 1024 < this.fileSize;
      if (!isLt2M) {
        this.$message.error('上传图片大小不能超过 '+this.fileSize+'KB!');
      }
      // 验证上传图片的宽和高
      let width = this.imgWidth;
      let height = this.imgHeight;
      if(typeof(width) == "undefined" && typeof(height) == "undefined"){
        isLt2M
      }else{
        const isSize = new Promise(function(resolve, reject) {
          let _URL = window.URL || window.webkitURL;
          let img = new Image();
          img.onload = function() {
            let valid = img.width >= width && img.height >= height;
            valid ? resolve() : reject();
          }
          img.src = _URL.createObjectURL(file);
        }).then(() => {
          return file;
        }, () => { this.$message.error("上传的icon必须是等于或大于"+this.imgWidth+"*"+this.imgHeight+"!");
          return Promise.reject();
        }); 
        return isLt2M && isSize;
      } 
    }, //图片上传成功
    handleAvatarSuccess(res, file,fileList) {
      if(res.status == 0){
        this.$message.error(res.msg)
        this.$refs['upload'].clearFiles()
        return false
      }
      this.imgList = fileList
      this.fileList = fileList
      this.$emit('getImgList',this.handleImage())
      this.isShow()
    }, //图片上传超过数量限制
    handleExceed(files, fileList) {
      this.$message.error('上传图片不能超过'+this.imgLimit+'张!')
      this.imgList=fileList
      this.$emit('getImgList',this.imgList)
    }, //图片上传失败调用
    imgUploadError(err, file, fileList){
      this.$message.error('上传图片失败!')
      this.$emit('getImgList',fileList)
      this.isShow()
    },
     /**
      * 处理获取服务地址转成本地查看
      * type:图片数量
      * parameter:图片参数
      */
    imageConversion:function(type,parameter){
      let imgList=[]
      //多图上传
      if(type>1){
        if(parameter){
          for (let i = 0; i < parameter.length; i++) {
            let img={
              url:parameter[i],
              response:'',
            }
            imgList.push(img);
          }
        }
        return imgList
      }
      //单图上传
      else{
        if(parameter){
          let img={
            url:parameter,
            response:'',
          }
          imgList.push(img)
        }
        return imgList
      }
    } 
  }
}
</script>
<style lang="scss" scoped>
 // 上传前
 /deep/ .el-upload--picture-card {
 width: 80px;
 height: 80px;
 line-height: 80px;
 }
 // 上传后
 /deep/ .el-upload-list__item {
 width: 80px;
 height: 80px;
 }
 // 隐藏上传
 /deep/ .hide .el-upload--picture-card {
 display: none;
 }</style>

组件使用如下:

<upload-image
 :action="action"
 :imgLimit="10"
 :fileSize="500"
 :imgWidth="900"
 :imgHeight="600"
 :fileListStr="thumb"
 @getImgList="(val)=>{thumb = val}"
></upload-image>
阅读 4.1k
1 个回答

你的图片列表是和 imageList 绑定的. 你的 handleAvatarSuccesshandleRemove逻辑中都有多次操作 imageList 的操作,导致了页面多次渲染图片列表的动作,你把上述两个方法中的 this.$emit('getImgList',this.handleImage()); 这段代码去掉看看

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题