intersectionobserver 不需防抖,应通过时间戳校验停留时长与交叉比来判定有效曝光:当 intersectionratio ≥ 0.3 且持续 ≥ 300ms(小程序 400–500ms)并首次上报时才触发,配合 root 隔离、动态监听与状态清理确保准确。

防抖本身不直接配合 IntersectionObserver,因为 IntersectionObserver 本身是异步、低频、基于浏览器渲染管线的观察机制,天然规避了 scroll 防抖的需求。真正需要“停顿后触发”的,不是防抖,而是时长校验 + 状态隔离——这是防止滚动中闪现、抖动、快速划过导致误报的核心。
为什么不能靠防抖来等“停顿”
滚动过程中,IntersectionObserver 的回调可能在用户尚未停顿时就已触发(比如 banner 刚进入视口 120ms 就触发 entry)。此时若用防抖(如 debounce(300ms))包裹上报逻辑,会把所有中间状态都延迟合并,导致:
• 首次进入时延后 300ms 才判断,但用户可能已在第 200ms 离开,实际未停留;
• 多次进出视口会被压缩成一次,丢失“再次曝光”信号;
• 无法区分“真停留”和“短暂掠过”。
正确做法:用时间戳做停留判定
每个广告/模块元素需独立维护曝光起始时间,并结合交叉比与持续时长决策:
macOS 微信消息自动化工具。通过 GUI 自动化实现:发送消息给指定联系人、读取聊天内容、监控新消息。适用于需要自动化微信操作的场景,如定时发送、批量回复、消息备份等。依赖 peekaboo 进行屏幕截图和 UI 交互。仅支持 macOS。开源地址:https://github.com/chairmanmia...
- 当
entry.isIntersecting === true且entry.intersectionRatio >= 0.3时,记录当前时间:el.dataset.exposureStart = Date.now().toString() - 仅当满足以下全部条件才视为有效曝光:
–entry.intersectionRatio >= 0.3
–Date.now() - Number(el.dataset.exposureStart) >= 300(行业通用下限)
– 该元素此前未上报过本次曝光(可用el.dataset.exposed = 'true'标记) - 上报成功后,清空
exposureStart和exposed,允许下次重新进入时再次计时
应对快速滚动与容器嵌套的细节
滚动快、页面结构复杂时,单纯依赖全局视口易失效:
- 为每个广告区域显式指定
root:信息流广告用.feed-container,弹窗广告用.modal-content,避免因父容器 overflow 而漏判 -
rootMargin不设为负值“提前触发”,而应匹配容器内边距(如'20px 0'),确保计算起点准确 - Tab 切换或动态插入的广告,必须调用
observer.observe(adEl)重新监听;销毁前务必unobserve,否则内存泄漏且状态错乱
小程序与 H5 的阈值微调
平台渲染节奏不同,需差异化设置最小停留时长:
- H5 页面:统一用 300ms(兼顾性能与准确性)
- 微信小程序:建议上调至 400–500ms,因小程序 WebView 渲染延迟略高,且
relativeToViewport的检测频率不如原生 IntersectionObserver 稳定 - 首屏广告可绕过 IntersectionObserver,在 DOM ready 后立即打点(附
isFirstScreen: true),避免白屏期错过曝光










