IntersectionObserver 是当前唯一合理选择,因其原生异步、不阻塞主线程、精准感知视口进出、支持 threshold 配置、兼容主流浏览器且适配复杂布局;曝光上报须加 500ms 时长校验,动态元素应复用 observer 实例并及时 unobserve,上报数据需持久化至 localStorage 以保障送达。

直接用 IntersectionObserver,别手写 getBoundingClientRect + scroll 监听 —— 性能差、容易漏报、兼容性还不好处理。
为什么 IntersectionObserver 是当前唯一合理选择
手动滚动监听 + 位置计算会频繁触发回流(layout),尤其在长列表或动画中,getBoundingClientRect 调用一次就可能让帧率掉到 30fps 以下;而 IntersectionObserver 是浏览器原生异步回调,不阻塞主线程,且能准确感知元素进出视口的时机。
- 它不依赖滚动事件,即使用户用键盘方向键、触控板惯性滑动、或
scrollIntoView触发,也能捕获 - 支持配置
threshold(比如设为[0, 0.1, 0.5, 1]),可区分“刚露头”“一半可见”“完全可见”等状态 - 对
position: fixed、transform、iframe 内嵌内容等复杂场景也稳定,手写方案基本扛不住 - 兼容性已不是问题:Chrome 51+、Firefox 55+、Safari 12.1+、Edge 79+;iOS Safari 12.2+;微信 WebView(X5 内核)从 2021 年起已全量支持
曝光上报必须加 500ms 阈值,否则数据严重失真
用户快速滚动时,元素可能在视口内只停留几十毫秒,这种“闪现”不能算有效曝光。所有生产环境的曝光逻辑都必须带最小可见时长判断,IntersectionObserver 本身不提供时间维度,得自己记时间戳。
- 在
entry.isIntersecting === true时,记录entry.target的首次相交时间(Date.now()),存进 Map 或 dataset,比如:el.dataset.observeStart = Date.now().toString() - 当
entry.isIntersecting === false或再次回调且entry.intersectionRatio > 0时,检查Date.now() - Number(el.dataset.observeStart) >= 500 - 只有满足时长才触发上报,同时清空
dataset.observeStart,避免重复计数 - 注意:不要只依赖
isIntersecting开关——它可能因防抖、节流或 observer 暂停而延迟触发,必须结合时间判断
动态插入的元素要重新 observe,但别每次都 new Observer
Vue/React 渲染列表、分页加载、懒加载图片后插入的 DOM,不会自动被已有 IntersectionObserver 实例观测。但每次新增都 new IntersectionObserver(...) 会造成内存泄漏和性能浪费。
生成可在 deepbi 沙箱 iframe 内运行或作为独立文件运行的交互式 HTML 页面,使用 `window.deepbi` JS SDK 实现数据查询、空间管理、文件浏览及用户操作。当用户提出以下需求时启用该能力: - 创建 KPI 仪表盘、数据表格、文件浏览器、成员列表、管理页面; - 明确要求“转成 dhtml”、“转译成 HTML”、“把 XX 页面转成……”、“控制台页面”、“管理后台”、“DeepBI 页面迁移”; - 提及位于 `apps/console/src/featur
- 复用同一个实例:全局只初始化一个
IntersectionObserver,然后对新元素调用observer.observe(el) - 确保元素已挂载到 DOM 再 observe —— React 可在
useEffect里做,Vue 可用nextTick或mounted钩子 - 元素销毁前务必调用
observer.unobserve(el),否则 observer 会持续持有 DOM 引用,导致无法 GC - 如果用自定义指令(如 Vue 的
v-expose),指令的unmounted钩子里必须 unobserve,这是最容易被忽略的内存泄漏点
上报队列要用 localStorage,别只靠 sessionStorage
用户划到页面底部,还没来得及上报就关闭标签页?或者网络临时中断?只存在 sessionStorage 里的待上报数据就丢了。真实埋点系统必须保证“至少送达一次”。
-
sessionStorage只用于暂存“正在观测中”的元素(如to-observe队列),关页即清,合理 - 真正要上报的数据(
to-report)必须写入localStorage,并在页面加载时检查是否有残留,有则立即重试上报 - 上报成功后,从
localStorage中移除对应条目;失败则保留,下次启动再试(建议加重试次数限制,比如最多 3 次) - 注意
localStorage.setItem可能抛错(比如用户禁用或空间满),需 try/catch 包裹,失败时降级为内存队列并 warn
最常被绕过的细节是:没处理 observer 回调中 entries 的遍历顺序与实际 DOM 插入顺序不一致的问题——这会导致同一屏多个模块的曝光时序错乱。如果业务要求严格保序(比如首屏模块 A 必须在 B 之前曝光),得在 observe 前按 DOM 顺序预存索引,不能只信回调顺序。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










