商品图预览用Object URL时,可以让一个小对象负责替换与释放,避免每次选文件只增加新地址却不清理旧引用。createObjectURL产生浏览器内部可引用的资源地址,revokeObjectURL在不再需要时释放对应引用。[1][2] 下面把图片预览的生命周期放在同一个管理对象里。
商品图预览用Object URL时,可以让一个小对象负责替换与释放,避免每次选文件只增加新地址却不清理旧引用。createObjectURL产生浏览器内部可引用的资源地址,revokeObjectURL在不再需要时释放对应引用。[1][2] 下面把图片预览的生命周期放在同一个管理对象里。
场景是员工反复查看候选图:上传、退回、重新选择,再关闭预览。地址不是发布链接,不能复制给其他员工当长期图片URL,也不是文件来源证明。它只在当前浏览器环境服务于预览,长期交付仍需实际文件与版本记录。
新地址成功建立后再替换旧地址
replace先建立next,再设置image.src;创建失败时current保持原值,设置失败则释放刚创建的新引用。赋值成功后释放旧引用,clear移除src并释放current,dispose可以重复调用而不重复释放。它管理的是直接挂在这个img上的预览,不管理其他组件共享的URL。

export function makePreview(image,api=URL) {
let current=null, disposed=false;
return {
replace(blob) {
if(disposed) throw Error('preview disposed');
const next=api.createObjectURL(blob);
const old=current;
try { image.src=next; current=next; }
catch(error) { api.revokeObjectURL(next); throw error; }
if(old) api.revokeObjectURL(old);
return next;
},
clear() { image.removeAttribute('src'); if(current)api.revokeObjectURL(current); current=null; },
dispose() { if(!disposed){ this.clear(); disposed=true; } }
};
}
把模块放在静态服务中,在浏览器导入makePreview,传入img元素,再在文件选择回调中传入File或Blob。api默认使用URL,也允许注入一个测试替身。关闭页面里的预览组件时调用dispose,不将清理函数留在只有某个按钮才能触发的位置。
验证释放顺序和失败情况
本次在Edge无头浏览器注入记录型api,依次选择first与second:替换后first被释放,clear后second被释放。重复dispose没有新增释放;dispose之后replace被拒绝。另让createObjectURL在输入bad时抛错,旧src保持first。验证覆盖管理逻辑,不是内存占用性能测试。
这里在设置新src之后释放旧地址,适合不再需要旧图片的简单预览。若旧地址还用于其他元素、下载或比较视图,必须由共享的所有者延后释放,不能每个组件各自清理同一个资源。资源所有权不清楚,正确调用API也可能让另一处功能失效。
图片加载失败与地址创建失败不同。代码只捕获建立地址和设置src的同步异常,不处理后续解码错误;调用者应监听加载状态、提供错误提示,并按流程清理。预览空白不自动表示文件不合法,也不能因此让生成系统无理由重复制作同一商品图。
Picset或其他来源的图像交付到员工浏览器后,[3] 这类管理可用于本地选择预览,代码并不是产品已有组件或发布接口。图像来源、SKU与审核记录仍要保留,Object URL不能取代它们。预览负责人应知道哪个版本被选中,而不只保存一个临时字符串。
清理时不要将组件生命周期与长期文件删除混在一起。revokeObjectURL不是删除磁盘文件,也不撤回已发布内容;它结束的是本页对资源的引用。将这些含义分清,员工在替换与关闭预览时得到稳定操作,交付系统也不会把临时浏览行为误记为商品文件已经被删或发布。