JavaScript点击同级元素删除内存Image()对象 避免已删预览图上传
问题根源
你只是删除了预览图片的DOM元素,存储在原生文件选择器fileUploader的files属性里的原始文件列表并未被修改,表单提交时默认读取的是该属性的文件列表,所以已删除预览的图片依然会被上传。之前修改thumbnailElement、置空等操作不生效,就是因为没有修改到实际提交时读取的文件列表。
解决方案
核心思路是自行维护当前有效的选中文件列表,删除预览时同步更新该列表和原生input的files属性,同时释放预览用的对象URL避免内存泄漏。
修改后的完整JS代码
const dropZone = document.getElementById('drop-zone'), showSelectedImages = document.getElementById('show-selected-images'), fileUploader = document.getElementById('standard-upload-files'), form = document.getElementById('upload-images-form') // 全局维护当前有效选中的图片文件列表 let selectedFiles = [] dropZone.addEventListener("click", (evt) => { fileUploader.click(); }); // 阻止拖放默认行为 dropZone.addEventListener("dragover", (evt) => { evt.preventDefault(); }); fileUploader.addEventListener("change", (evt) => { showSelectedImages.innerHTML = ""; // 过滤仅保留图片文件,更新自定义文件列表 selectedFiles = [...fileUploader.files].filter(file => file.type.startsWith("image/")) selectedFiles.forEach(updateThumbnail); }); dropZone.addEventListener("drop", (evt) => { evt.preventDefault(); showSelectedImages.innerHTML = ""; // 过滤仅保留图片文件,更新自定义文件列表 const droppedFiles = [...evt.dataTransfer.files].filter(file => file.type.startsWith("image/")) selectedFiles = droppedFiles // 同步更新原生input的文件列表 if (droppedFiles.length) { const dataTransfer = new DataTransfer() droppedFiles.forEach(file => dataTransfer.items.add(file)) fileUploader.files = dataTransfer.files } selectedFiles.forEach(updateThumbnail); }); // 生成预览图 function updateThumbnail(file, index) { const uploadImageWrapper = document.createElement('article'), removeImage = document.createElement('div'), thumbnailElement = new Image(); removeImage.classList.add("remove-image"); removeImage.innerHTML = 'x'; thumbnailElement.classList.add("drop-zone__thumb"); // 存储对象URL,后续删除时释放 const previewUrl = URL.createObjectURL(file) thumbnailElement.src = previewUrl; showSelectedImages.append(uploadImageWrapper) uploadImageWrapper.append(removeImage) uploadImageWrapper.append(thumbnailElement); // 删除图片逻辑 removeImage.addEventListener('click', (evt) => { // 1. 从自定义文件列表中删除对应文件 selectedFiles.splice(index, 1) // 2. 释放对象URL,避免内存泄漏 URL.revokeObjectURL(previewUrl) // 3. 删除预览DOM uploadImageWrapper.remove() // 4. 同步更新原生input的文件列表,兼容默认表单提交逻辑 const dataTransfer = new DataTransfer() selectedFiles.forEach(file => dataTransfer.items.add(file)) fileUploader.files = dataTransfer.files }) }
可选优化:自定义表单提交
如果需要完全控制提交逻辑,可以拦截表单默认提交行为,用维护的selectedFiles构建表单数据提交:
form.addEventListener('submit', (e) => { e.preventDefault() const submitData = new FormData() // 添加有效图片文件 selectedFiles.forEach(file => { submitData.append('standard-upload-files[]', file) }) // 补充其他提交字段 submitData.append('submit-images', 'SUBMIT IMAGES') // 替换为你的PHP上传接口地址 fetch('/your-upload-api.php', { method: 'POST', body: submitData }).then(res => res.json()) .then(result => { // 处理上传成功后的逻辑,比如提示、跳转 }).catch(err => { // 处理上传失败逻辑 }) })
内容的提问来源于stack exchange,提问作者pjk_ok
相关产品推荐
相关产品推荐

