使用Intersection Observer调用API仅触发一次问题排查求助
问题排查与解决方案
核心问题分析
IntersectionObserver配置错误
你设置了threshold: [1.0],这要求目标元素完全进入视口才触发回调。但加载新内容后,#ajax-card-grid__items的高度会超过视口高度,此时整个元素永远无法完全处于视口内,导致Observer后续不再触发。无防重复触发机制
滚动过程中可能多次触发交叉状态变化,容易导致重复调用API,需要添加加载状态锁。缺失无更多数据时的停止监听逻辑
当接口返回无更多数据时,未停止Observer监听,会产生无效的触发检查。
修改后的代码
1. 调整IntersectionObserver逻辑与配置
let isLoading = false; // 防重复请求锁 const observer = new IntersectionObserver((entries) => { entries.forEach((entry) => { // 仅当元素进入视口且未在加载时执行 if (!entry.isIntersecting || isLoading) { return; } isLoading = true; triggerProductCards($(selectorCardGrid)).then(() => { isLoading = false; // 检查是否还有更多数据,无数据则停止监听 const hasMore = $(selectorCardGrid) .closest(".ajax-card-grid__content") .find(".ajax-card-grid__more-link") .hasClass("active"); if (!hasMore) { observer.unobserve(entry.target); } }); }); }, { threshold: 0, rootMargin: "0px 0px -1px 0px" // 当元素底部刚好进入视口时触发 }); const target = document.getElementById('ajax-card-grid__items'); observer.observe(target);
2. 优化triggerProductCards函数
const triggerProductCards = function(triggerEvent) { var query = currentQuery(); query.grid_type = triggerEvent .closest("[data-layer-grid-type]") .attr("data-layer-grid-type"); query.action_type = "results"; query.page_id = triggerEvent .closest(".card-grid-results") .attr("data-layer-page-id"); query.page_revision_id = triggerEvent .closest(".card-grid-results") .attr("data-layer-page-revision-id"); if (query.grid_type === "grid") { query.grid_id = triggerEvent .closest(".card-grid-results") .attr("data-layer-grid-id"); $(".ajax-card-grid__more-link").css({'pointer-events':'none', 'opacity':'0.6'}); } var selectorContext = triggerEvent; var searchItems = selectorContext .closest(".ajax-card-grid__content") .find(".ajax-card-grid__items"); query.offset = searchItems.children().length; if (query.grid_type === "grid" || query.grid_type === "search_page") { query.limit = Drupal.behaviors.loadMorePager.getLimitByGridType( query.grid_type ); } return $.ajax({ url: drupalSettings.path.baseUrl + drupalSettings.path.pathPrefix + "search-callback", data: query, success: function (data) { if (data.results !== null) { data.results.forEach(function (element) { var elementWrapper = document.createElement("div"); elementWrapper.className = "ajax-card-grid__item_wrapper"; elementWrapper.innerHTML = element; searchItems.append(elementWrapper); Drupal.behaviors.productCard.attach(searchItems); }); // 明确标记是否还有更多数据 const moreLink = selectorContext .closest(".ajax-card-grid__content") .find(".ajax-card-grid__more-link"); if (!data.pager) { moreLink.removeClass("active"); } else { moreLink.addClass("active"); } } setTimeout(function () { $('.ajax-card-grid__more-link').removeAttr('style'); }, 500); }, beforeSend: function() { $(selectorCardGrid).removeClass("back-to-default"); if(drupalSettings.mars_product.loader) { $('.cv-spinner').addClass('pager'); $("#overlay").show(); } }, complete: function () { if(drupalSettings.mars_product.loader) { setTimeout(function(){ $("#overlay").fadeOut(300); $('.cv-spinner').removeClass('pager'); },500); } $(selectorCardGrid).addClass("back-to-default"); setTimeout(function () { $('.ajax-card-grid__more-link').removeAttr('style'); }, 500); }, }); }
关键修改说明
- 调整Observer配置:将
threshold: [1.0]改为threshold: 0并添加rootMargin,确保元素底部刚进入视口就触发回调,适配加载更多后的元素高度变化。 - 添加
isLoading锁:避免滚动过程中重复调用API。 - 新增无数据停止监听逻辑:当接口返回无更多数据时,自动停止Observer监听,减少无效操作。
- 优化更多数据标记:明确处理
active类的添加/移除,确保状态判断准确。
内容的提问来源于stack exchange,提问作者Thajudeen K
相关产品推荐
相关产品推荐

