背景
- 最近工作中遇到一个问题,即曝光埋点的上传
- 已有的函数
// 判断dom元素是否在可视窗口内,使用getBoundingClientReact方案实现的 const isInViewPort = (dom) => {}; // 发送曝光埋点请求 const sendExposeBuriedPoint = (config) => {};
- 限制条件:不能监听
scroll
事件来判断元素是否曝光
方案
- 元素渲染后,因为使用的框架为
Vue2
,即mounted
中做如下事情: - 结合上述方案,最终决定采用 【
IntersectionObserver
+polyfill
】 >>>【定时器
+getBoundingClient
】
IntersectionObserver的好处
异步API
scroll
和resize
事件、定时器
的频繁触发,会导致JS线程阻塞GUI渲染线程,而IntersectionObserver类似requestIdleCallbackAPI在渲染一帧的空闲时间才会触发,避免了阻塞UI渲染
isInViewport
- 替代
getBoundingClient
来判断DOM是否曝光- ① 指定
threshold
的值(intersectionRatio
大于的阈值),即root element
和target element
相交的触发时机 - ② 通过
isIntersection && intersectionRatio >= 0.5
来记录曝光埋点
- ① 指定
- 实现一些资源的懒加载(
按需加载
)
isVisible
- 能通过
IntersectionObserverEntry
的isVisible
属性目标元素是否实际可见,如在一个网站上有广告的透明度为0,覆盖在别的吸引人的内容上,诱骗人们点击以谋取利益(Trust is good, observation is better: Intersection Observer v2的参考案例)
rootMargin
- 初始化时的option可配置rootMargin,即控制root element和target element相交的范围,如设置rootMargin的底部为100px,触发回调时就可以做一些资源的预加载(
提前请求
)
后话
- 实际上我并没有采用调用的【
IntersectionObserver
+polyfill
】 的方案去实现,而是采用了【定时器
+getBoundingClient
】的方案,对此我对方案的选择有了新的认知- 方案它的兼容性如何,因为我这边要适配的IOS、andirod的版本和机型很多,为了保险起见(
防止生产上出现事故
),并不是说方案的性能好就可以直接上的,如果业务仅需要支持最新版的chrome✅,那就随便玩了,但实际上不能如此
- 方案它的兼容性如何,因为我这边要适配的IOS、andirod的版本和机型很多,为了保险起见(