如何获取滚动时用户当前视口内可见的product类产品元素
获取视口内可见product元素的实现方案
问题场景
产品列表滚动时视口固定展示3个产品,所有产品的类名均为product,示例DOM结构如下:
<div class="product"> <span>price:2</span> </div> <div class="product"> <span>price:2</span> </div>
需要拿到当前浏览时刻视口内可见的3个产品元素。
实现方法
方法1:基于getBoundingClientRect遍历判断
这个方案兼容性覆盖所有主流浏览器,逻辑直接,通过元素相对视口的位置信息判断是否处于可见范围:
// 预取所有产品元素、视口高度 const products = document.querySelectorAll('.product'); const viewportH = window.innerHeight; /** * 获取当前视口内可见的产品元素 * @returns {Element[]} 可见产品集合 */ function getVisibleItems() { return Array.from(products).filter(item => { const rect = item.getBoundingClientRect(); // 元素和视口有相交即判定为可见 return rect.top < viewportH && rect.bottom > 0; }); } // 滚动时触发获取,加防抖避免高频执行损耗性能 let scrollTimer = null; window.addEventListener('scroll', () => { if (scrollTimer) clearTimeout(scrollTimer); scrollTimer = setTimeout(() => { const visibleItems = getVisibleItems(); // 这里拿到的visibleItems就是当前视口内的3个产品,可直接做后续DOM操作 console.log(visibleItems); }, 80); });
如果需要判定元素完全处于视口内才计入,把过滤条件替换为
rect.top >= 0 && rect.bottom <= viewportH即可,你的场景下用默认的相交判断逻辑,就能准确拿到3个可见元素。
方法2:基于IntersectionObserver实现(长列表性能更优)
如果产品列表很长,优先用浏览器原生的相交观察器,不需要绑定scroll事件做高频遍历,性能表现更好:
// 用集合存储当前可见元素,自动去重 const visibleSet = new Set(); const observer = new IntersectionObserver(entries => { entries.forEach(entry => { entry.isIntersecting ? visibleSet.add(entry.target) : visibleSet.delete(entry.target); }); // 集合转数组就是当前可见的产品列表 const visibleItems = Array.from(visibleSet); console.log(visibleItems); }, { threshold: 0 }); // 给所有产品元素绑定观察 products.forEach(item => observer.observe(item));
根据项目兼容要求选其中一种用就行,两种方案都能准确拿到视口内的3个.product元素。
内容的提问来源于stack exchange,提问作者Gök Han Güneş
相关产品推荐
相关产品推荐

