choose回调中必须用obj.pushfile()获取待上传文件映射对象,其key为自增字符串、value为file实例;需存于闭包或模块变量,删除时同步删缓存、dom及状态。

choose 回调里必须用 obj.pushFile() 拿到当前文件队列
layui 不暴露 files 属性给外部,obj.pushFile() 是唯一能拿到当前待上传文件映射对象的入口。它返回的是一个键值对对象,key 是自增字符串(如 "1612418956647-0"),value 是原生 File 实例。
常见错误是直接用 uploadInst.files 或试图遍历 $('img') 顺序来匹配——DOM 插入顺序和文件入队顺序不保证一致,多选时极易错位。
- 在
choose回调第一行就执行const files = obj.pushFile() - 把
files存到闭包或模块级变量(如let PENDING_FILES = {})中,供后续删除逻辑使用 - 不要在
choose里写uploadInst.files = [],这会破坏后续done中的index参数有效性
预览图 DOM 必须绑定对应文件的 index 键
点击某张缩略图要删掉它,关键不是“删这张图”,而是“删它背后那个 File 实例”。所以每个 <img> 或其容器节点必须携带该文件在 files 对象里的 key。
- 在
obj.preview回调里,用$(img).data('index', index)把index存进 DOM - 或者用闭包方式:在
preview内部直接捕获当前index和file,绑定事件时直接引用 - 避免用
$('.uploader-list img').eq(i)这类靠索引的操作,DOM 重排、异步插入都会导致错位
删除动作必须三步同步:删缓存 + 删 DOM + 清状态
只删 DOM 图片,下次点上传按钮仍会提交;只删 files[index],UI 上图片还挂着;漏掉任何一步,状态就不同步。
- 通过事件委托拿到触发元素:
$(e.target).closest('.file-iteme').find('img').data('index') - 执行
delete PENDING_FILES[index](注意是delete,不是PENDING_FILES.splice) - 移除整个预览容器:
$(e.target).closest('.file-iteme').remove() - 如果所有文件都删完了,建议手动清空 UI 提示文字或隐藏上传按钮,避免用户误点
multiple: true 下容易忽略的边界情况
多图场景下,用户反复点“选择文件”,obj.pushFile() 会不断追加新项,旧的没清理就会堆积。这不是 bug,是设计使然——layui 默认累积,需主动干预。
- 每次
choose开头先清空上一轮残留:for (let k in PENDING_FILES) delete PENDING_FILES[k] - 如果业务允许单图,删完后立即用
obj.pushFile()[Object.keys(obj.pushFile())[0]]取最新一个并重新赋值 - 弹窗内使用时,打开前必须重置
PENDING_FILES = {},否则关掉再打开,内存里还存着“幽灵文件”
最常被跳过的细节是:没确认 PENDING_FILES 是否还在作用域内。函数执行完就销毁,闭包没兜住的话,delete 操作实际删的是空对象。











