cropper.js仅第二次上传调用destroy报removeChild为null错误如何解决
问题原因分析
- 手动移除DOM未销毁实例:你在裁剪提交逻辑中直接调用
$('.cropper-container').remove()删除了Cropper生成的容器节点,但没有调用实例的destroy方法销毁实例,也没有清空原图片元素上的cropper引用。第二次触发初始化时,图片元素上还保留着之前的cropper实例,但实例关联的DOM节点已经被你手动删除,调用destroy方法时要操作不存在的DOM节点就触发了Cannot read property 'removeChild' of null报错。 - 销毁顺序错误:现有代码中你先清空了图片的src属性,再调用destroy方法,src清空后Cropper相关的关联结构已经被破坏,也会导致destroy执行异常。
- 事件重复绑定:每次调用
initCropper都会给裁剪按钮新增一个点击事件监听,多次初始化后点击一次提交会触发多次上传逻辑;同时每次上传都给图片新增load事件监听,也会导致initCropper被多次调用。
修复方案
- 调整销毁逻辑:优先判断图片上是否存在cropper实例,存在的话先调用destroy方法,销毁实例的同时它会自动清理生成的DOM节点,不需要你手动删除。
- 移除手动删除
.cropper-container的代码,交给destroy方法处理。 - 事件绑定前先解绑旧的监听,避免重复绑定。
- 用完的Blob URL主动调用
URL.revokeObjectURL释放内存。
修复后完整代码
const bannerInput = document.getElementById('id_edit_banner'); const avatarInput = document.getElementById('id_avatar'); // 全局保存cropper实例方便管理 let cropper = null; function uploadPhoto(uploadElem) { let blobUrl = URL.createObjectURL(uploadElem.files[0]); const $dragImage = $('#drag-image'); // 先解绑之前的load事件避免重复触发 $dragImage.off('load').on('load', (e) => { // 用完就释放blobUrl URL.revokeObjectURL(blobUrl); initCropper(); }).attr('src', blobUrl); } $(document).on('change', '#id_avatar', e => { uploadPhoto(avatarInput) }); function initCropper() { var image = document.getElementById('drag-image'); // 先判断是否有已存在的cropper实例,有就先销毁 if (cropper) { cropper.destroy(); cropper = null; } // 初始化新的cropper实例 cropper = new Cropper(image, { aspectRatio: 1 / 1, }); // 先解绑旧的点击事件避免重复绑定 $('#crop-submit').off('click').on('click', function () { $('.update-img-container').addClass('d-none'); cropper.getCroppedCanvas().toBlob(function (blob) { var formData = new FormData(); formData.append('avatar', blob, 'avatar.jpg'); formData.append('csrfmiddlewaretoken', $('input[name=csrfmiddlewaretoken]').val()); $.ajax({ url: `/update-avatar/`, method: "POST", data: formData, processData: false, contentType: false, success: function () { // 上传成功后销毁实例 if (cropper) { cropper.destroy(); cropper = null; } }, error: function () { if (cropper) { cropper.destroy(); cropper = null; } } }); }); }); }
内容的提问来源于stack exchange,提问作者user14490044
相关产品推荐
相关产品推荐

