elementui 图片上传闪烁问题

最近用elementui的upload组件的时候,发现图图片的加载会出现一开始图片居中显示,然后才显示在正常的位置,如下所示(仓促制成,很模糊,见谅):
MyVideo_1.gif

希望各位能帮忙解惑,感激!

阅读 12.4k
5 个回答

问题已解决,是由于父子组件传值,在子组件中监听了父组件的文件列表数据导致的。
错误代码如下:

<!-- 父组件 -->
<Upload :file-list="fileList" ref="uploadCom"
        @setFileList="setFileList">
</Upload>
//组件数据初始化
initData(val){
    this.$set("fileList",val.fileList)
}
setFileList (list) {
    this.fileList = list
},


<!-- 子组件 -->
<template>
    <el-upload
      list-type="picture-card"
      :file-list="initList">
    </el-upload>
</template>

watch: {
    fileList: function () {
      this.initList = this.fileList
    }
}

由于在子组件中监听了fileList,当文件上传成功时,父组件给fileList重新赋值,fileList改变,子组件触发监听事件,导致<el-upload>又重新初始化上传文件列表一次。(一开始设置监听fileList是为了方便在initData初始化父组件数据时获取了文件列表后传给子组件,才有了这一系列的问题)
解决代码如下:

<!-- 父组件 -->
<Upload :file-list="fileList" ref="uploadCom"
        @setFileList="setFileList">
</Upload>
//组件数据初始化
initData(val){
    this.$set("fileList",val.fileList)
    //在这里获取了文件数据后,
    //触发子组件的方法初始化<el-upload>文件列表
    this.$refs.uploadCom.initFileList();
}
setFileList (list) {
    //this.fileList = list
    //重新定义一个变量存储回传成功的文件数据
    this.newFileList = list
},


<!-- 子组件 -->
<template>
    <el-upload
      list-type="picture-card"
      :file-list="initList">
    </el-upload>
</template>


//不再使用监听方法
//当然在父组件中用newFileList存储回传成功的
//文件数据之后,使用监听也没有问题,因为不会再
//触发监听事件了,但是只需要初始化<el-upload>的
//文件数据还是不用监听了,定义方法初始化就好了
/*watch: {
    fileList: function () {
      this.initList = this.fileList
    }
}*/
methods: {
    //初始化文件数据
    initFileList(){
      this.initList = this.fileList
    },
}

遇到了同样的问题,就是上传过程中图片向右侧偏移,上传完后回到本来的位置,表现为闪烁了一下。
我是因为上传成功后赋值的方式引起的。我是将每次上传成功后将那一次的file对象push进file-list回显的对象中:

<el-upload :file-list="formData.files" 
           :on-success="handleUploadSuccess"></el-upload>

handleUploadSuccess(res, file, fileList){
    this.formData.files.push(file)
},

之后我改成将flieList整体赋值,就不会有这个问题了:

handleUploadSuccess(res, file, fileList){
    this.formData.files = fileList
},

动态图太小看不到效果

element ui的upload组件 图片上传 闪动/闪烁/跳动/闪动

试了几种修改css的解决方案
/deep/ .el-upload-list__item.is-ready {//这个对于list-type="picture-card"图片类型没用
display: none;
}

::v-deep .el-upload-list__item {//虽然不跳动了,但是还是会闪烁
transition: none !important;
}

.el-list-leave-active



一开始是这样写的
:file-list="一个方法aaa(imageList)"
imageList是['1111','2222']这样
aaa方法返回的是
[{url: 'https://fuss10.elemecdn.com/1111'}, {url: 'https://fuss10.elemecdn.com/2222'}]
这样的格式,拼接好了全部网址

这样写不行,最好不要在模板template/v-bind中使用方法method
否则每次dom更新(修改这个组件中的其它data属性导致dom更新)都会重新调用一次这个方法,导致file-list中的对象又变成了只有url一个属性(而实际上el-upload内部的fileList是经过修改的,有3个属性的
{

"url": "...",
"uid": 1698633668823,
"status": "success"

}(on-change回调方法输出)),导致需要再转换一下加入其它两个属性,然后就会闪烁一下
后来改成了
:file-list="[{ url: ... }]"
这样还是不行,这样根本添加不上新图片,就固定一个图片(新图片添加上了之后,又被:file-list=后绑定的固定的字面量,只有一个元素的数组,覆盖了)
:file-list这个属性其实类似于v-model,el-upload内部是会修改它的,加上两个属性
(到element-plus中就可以看到加上v-model了

v-model:file-list="fileList"

最后就是先在created里处理了一下imageList
this.imageListConverted = this.一个转换格式的方法(this.imageList)
改成了:file-list="imageListConverted"就可以了

其中还遇到了一个坑,就是我

handleSuccess(response, file, fileList) {
  this.imageListConverted = _.cloneDeep(this.imageListConverted);
  this.imageListConverted.push(file);
这里不要cloneDeep,深克隆之后,:file-list=后props传入el-upload的对象就会触发watch,然后
      handler(fileList) {
        this.uploadFiles = fileList.map(item => {
          item.uid = item.uid || (Date.now() + this.tempIndex++);
          item.status = item.status || 'success';
          return item;
        });
源码中this.uploadFiles(此时已经插入了新上传的文件元素)就会被新克隆的对象替换掉,新上传的文件就会消失,始终无法上传

再说一些我看的博客的一些问题
https://blog.csdn.net/qq_18188377/article/details/117534512
里边说

这里有一个坑!!!!那就是data中的fileList和钩子返回的fileList是不同步的(除了初始化,往fileList中添加数据,data中的fileList是不会改变的)。这里简单说下我的理解

确实是不同步的,绑定的data中的fileList数组中的个数是传入时就固定的(但是会修改,加上uid和status这两个属性)(更:看源码发现是通过watch后fileList.map,返回一个新数组uploadFiles
https://github.com/ElemeFE/element/blob/290e68ea6aa6c56b7d83182b650e3be4f77ff1b0/packages/upload/src/index.vue
看源码发现,闪烁/闪动效果的根本原因是修改了uid,:key="file.uid",如果uid变了/没了新生成,应该就会闪烁/闪动
https://github.com/ElemeFE/element/blob/290e68ea6aa6c56b7d83182b650e3be4f77ff1b0/packages/upload/src/upload-list.vue

所以我们上传成功后只需将返回的图片地址放入我们的表单中即可,无需对fileList进行操作。同理删除也是一样

也可以对fileList操作,只是要把handleSuccess(response, file, fileList)中的file push进去就行,关键是要带着uid,保持key对应的uid不变

https://blog.csdn.net/qq_41823450/article/details/122821173

不能直接将上传图片时的fileList属性绑定到file-list,需要用到on-success属性,将图片列表存到infoForm.effect中,再绑定到file-list上。

可以直接绑定到file-list,但是 1不要随便改file-list以免触发传入props后的watch覆盖uploadFiles数组 2如果要改file-list则要保证file-list中的uid不变

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