必须关闭 auto: true,否则 choose 回调中无法获取完整 FileList 导致预览失效;需用 Array.from(obj.files) 转为数组后遍历,用 /^image//.test(file.type) 过滤图片,且不可在 choose 中调用 obj.upload()。
必须关掉 auto: true,否则 choose 回调里拿不到完整 filelist,预览逻辑直接失效。
choose 回调里怎么拿到所有选中的图片
Layui 的 upload.render() 在 choose 回调中只传入一个 obj 对象,它的 obj.files 是原生 FileList,不是数组——不能直接用 forEach 或解构。
- 必须先转成数组:
Array.from(obj.files)或[...obj.files] - 每个
file有name、size、type,可用正则/^image\//.test(file.type)过滤非图片(如.pdf、.txt) - 别在
choose里调obj.upload(),否则文件立刻上传,预览还没开始就结束了 - 常见错误:用
for (let i = 0; i + <code>new FileReader(),闭包导致所有img.src都是最后一个文件的 base64
预览图怎么生成才不卡顿、不崩内存
readAsDataURL 把大图转成 base64 后体积膨胀约 33%,5MB 的 PNG 可能撑到 6.5MB 字符串,频繁操作易阻塞主线程。
- 优先用
URL.createObjectURL(file)快速生成临时地址,但必须在预览后手动URL.revokeObjectURL(),否则内存泄漏 - 若需缩略图尺寸控制(比如统一 120×120),得用
canvas绘制压缩后再转dataURL,不能靠 CSS 缩放——会模糊、拉伸、失真 - 移动端尤其要限制单图最大宽高(如
maxWidth: 800),否则 iPhone 拍的 4000×3000 图片读取时直接卡死 - 加
reader.onerror降级处理:读取失败时显示文件名 + 占位图标,而不是留白或报错中断
如何精确锁死上传张数(不是表单校验)
仅靠提交前检查 input 值长度或 JS 变量计数,用户仍可连续点击“选择文件”弹出多个系统对话框,造成体验断裂和 DOM 泄漏。
- 真正有效的锁是在 DOM 层拦截:每次
choose开始前,检查当前已选图片数是否已达上限(比如 5 张),超限则直接return并提示 - 注意清空逻辑:删除某张预览图时,不仅要移除
img元素,还要从保存的files数组中splice对应项,并重置upload实例的this.files - 别依赖
number: 5参数——它只限制单次选择数量,用户点两次仍能凑够 10 张;必须自己维护全局计数器 - 拖拽上传(
layui-upload-drag)也要同步监听drop事件做同样拦截,否则拖 10 张进来就失控
最易被忽略的是预览图的生命周期管理:每张图对应一个 FileReader 实例或 objectURL,删图时没清理,反复操作几次内存就飙到几百 MB。这不是“功能做完就行”的环节,而是决定系统能否稳定跑一整天的关键。


















