如何解决图库图片列表追加元素时出现的递归过多错误
解决DOMNodeInserted引发的递归溢出问题
嘿,这个递归溢出的问题我太熟悉了!核心原因是你使用的DOMNodeInserted事件会在你向DOM添加元素(就是那个显示"查看更多"的div)时再次被触发,导致你的代码反复执行,不断插入div,最终触发了"too much recursion"错误。
为什么会出现无限递归?
当你的代码执行到append('<div>...')这一行时,新的div被插入到DOM中,这个动作会再次触发DOMNodeInserted事件,你的事件处理函数又会重新跑一遍——统计图片数量、计算隐藏数量、再次append div,循环往复直到浏览器的调用栈被撑爆。
解决方案:避免重复执行逻辑
这里有两种可靠的解决思路,你可以根据场景选择:
方案1:给元素加标记,检查是否已添加过
最简单的修改方式是在插入div之前,先检查目标元素里是否已经存在这个统计div,如果存在就直接跳过后续逻辑。我们可以给div加一个唯一的类名(比如more-images-indicator)来做判断:
jQuery('.mapsvg-controller-view').on('DOMNodeInserted','.mapsvg-gallery-wrap', function() { var $gallery = jQuery('.mapsvg-gallery'); var $fourthFigure = $gallery.children().eq(3); // 先检查是否已经添加过统计元素,避免重复执行 if ($fourthFigure.find('.more-images-indicator').length > 0) { return; } // 直接用length统计图片数量,比each循环更高效 var galleryFigureNum = $gallery.find('figure').length; var moreImagesNum = galleryFigureNum - 4; // 插入带类名的统计div $fourthFigure.append('<div class="more-images-indicator">'+moreImagesNum+' View more</div>'); });
方案2:改用MutationObserver(更推荐)
DOMNodeInserted其实已经被官方标记为废弃API了,推荐使用更现代、更可控的MutationObserver来监听DOM变化。它可以精准控制要监听的内容,而且不会轻易触发递归:
// 找到要监听的父容器 var targetContainer = document.querySelector('.mapsvg-controller-view'); // 配置观察规则:只监听子节点的添加,并且深入子树 var observerConfig = { childList: true, subtree: true }; // 定义DOM变化时的回调函数 var handleGalleryInsert = function(mutations) { mutations.forEach(function(mutation) { // 检查新增的节点里有没有我们要找的图库容器 var $newGalleryWrap = jQuery(mutation.addedNodes).filter('.mapsvg-gallery-wrap'); if ($newGalleryWrap.length === 0) return; var $gallery = $newGalleryWrap.find('.mapsvg-gallery'); var $fourthFigure = $gallery.children().eq(3); // 同样先检查是否已添加过统计元素 if ($fourthFigure.find('.more-images-indicator').length === 0) { var totalImages = $gallery.find('figure').length; var hiddenImages = totalImages - 4; $fourthFigure.append('<div class="more-images-indicator">'+hiddenImages+' View more</div>'); // 如果图库只会加载一次,可以在这里断开观察,节省性能 observer.disconnect(); } }); }; // 创建观察者实例并启动观察 var observer = new MutationObserver(handleGalleryInsert); observer.observe(targetContainer, observerConfig);
额外优化小技巧
- 用
$element.find('figure').length代替each循环计数,代码更简洁,性能也更好。 - 如果你的图库是动态加载多次的,不要调用
observer.disconnect(),保持观察但每次都检查统计元素是否存在即可。 - 给统计div加类名不仅方便检查,还能让你更轻松地用CSS美化这个"查看更多"提示。
内容的提问来源于stack exchange,提问作者Oudin
相关产品推荐
相关产品推荐

