多图上传功能中如何关闭或删除指定已选预览图片的实现咨询
多图片预览加单个删除功能实现方案
核心逻辑说明
- 原生input的
FileList是只读属性,无法直接删除其中某一项,所以我们需要单独维护一个自定义的可编辑数组来存储待上传的图片文件 - 给每个预览图套一个独立的容器,容器内新增右上角的叉号删除按钮
- 点击删除按钮时同步删除3个内容:对应预览DOM节点、内存中缓存的Blob对象、自定义文件数组里的对应文件项
- 最终提交时用FormData携带我们维护的文件数组提交即可
完整代码实现
HTML
<input required name="imageUploader" type="file" multiple class="form-control-file" id="imageInput"> <p class="cont"></p>
CSS(用来调整删除按钮展示样式)
/* 预览项容器 */ .preview-item { position: relative; display: inline-block; margin: 10px 10px 0 0; } /* 删除按钮 */ .delete-btn { position: absolute; top: -8px; right: -8px; width: 20px; height: 20px; border-radius: 50%; background: #000; color: #fff; text-align: center; line-height: 20px; font-size: 14px; cursor: pointer; }
JavaScript
// 存储待上传文件的自定义数组 let uploadFiles = []; const imageInput = document.getElementById('imageInput'); const cont = document.querySelector('.cont'); // 监听文件选择事件 imageInput.addEventListener('change', function(e) { const files = e.target.files; for (let i = 0; i < files.length; i++) { // 把文件加入自定义数组 uploadFiles.push(files[i]); // 创建预览项容器 const previewItem = document.createElement('div'); previewItem.className = 'preview-item'; previewItem.dataset.index = uploadFiles.length - 1; // 绑定当前文件在数组中的索引 // 创建预览图 const image = document.createElement('img'); image.src = URL.createObjectURL(files[i]); image.width = 200; // 创建删除按钮 const deleteBtn = document.createElement('span'); deleteBtn.className = 'delete-btn'; deleteBtn.innerText = '×'; // 绑定删除事件 deleteBtn.addEventListener('click', function() { const index = parseInt(previewItem.dataset.index); // 释放Blob内存 URL.revokeObjectURL(image.src); // 删除数组中对应文件 uploadFiles.splice(index, 1); // 移除预览DOM previewItem.remove(); // 更新剩余预览项的索引,保证后续删除定位正确 document.querySelectorAll('.preview-item').forEach((item, idx) => { item.dataset.index = idx; }); }); // 拼接DOM previewItem.appendChild(image); previewItem.appendChild(deleteBtn); cont.appendChild(previewItem); } // 清空input value,允许重复选择同一张图片 imageInput.value = ''; }); // 提交示例:用FormData携带文件提交 function submitForm() { const formData = new FormData(); // 把自定义数组里的文件加入FormData,字段名和后端要求保持一致即可 uploadFiles.forEach((file, idx) => { formData.append('images', file); }); // 后续用AJAX提交formData即可 }
注意事项
- 不要使用表单默认提交方式,否则只能拿到原生input的原始文件列表,拿不到过滤后的文件,需要用AJAX携带上面生成的FormData提交
- 每次删除后调用
URL.revokeObjectURL()可以释放浏览器内存,避免内存泄漏 - 原代码中所有预览图共用同一个id是错误写法,优化代码中已经移除了重复id
内容的提问来源于stack exchange,提问作者Inayat Kazi
相关产品推荐
相关产品推荐

