IntersectionObserver API使用方法

C端开发过程中的mv埋点, 要求元素暴露在视口内, 用户可见时才上报mv埋点,有一种做法是判断元素的滚动距离,人工判断是否元素滚动进入视口,金刚位滚动,轮播的交互方式下,还要处理上报过的不再次上报的逻辑,这种做法十分麻烦。

原文参考:https://developer.mozilla.org/zh-CN/docs/Web/API/Intersection_Observer_API

神器 :Intersection Observer API

是什么?

检测目标元素与祖先元素相交情况变化的api。

应用场景:
  • 图片懒加载 ,当图片滚动到可见时才进行加载。
  • 内容无限滚动 , 用户滚动到接近页面底部时直接加载更多,无需操作翻页。这个我以往的处理还是判断滚动距离+节流 : https://km.sankuai.com/page/716538605

  • 在用户看到某个区域时,播放动画或执行任务。

工作机制:
  • Intersection Observer API 会注册一个回调函数,每当被监视的元素进入或者退出另外一个元素时(或者 viewport )设备视窗或者其他元素我们称它为根元素或根(root),或者两个元素的相交部分大小发生变化时,该回调方法会被触发执行。这样,我们网站的主线程不需要再为了监听元素相交而辛苦劳作,浏览器会自行优化元素相交管理。

  • 注意 Intersection Observer API 无法提供重叠的像素个数或者具体哪个像素重叠,他的更常见的使用方式是——当两个元素相交比例在 N% 左右时,触发回调,以执行某些逻辑。

  • 目标(target)元素与根(root)元素之间的交叉度是交叉比(intersection ratio)。这是目标(target)元素相对于根(root)的交集百分比的表示,它的取值在0.0和1.0之间。阈值为1.0意味着目标元素完全出现在root选项指定的元素中可见时,回调函数将会被执行。

用法:
  1. 创建一个 IntersectionObserver对象,并传入相应参数和回调用函数,该回调函数将会在目标(target)元素和根(root)元素的交集大小超过阈值(threshold)规定的大小时候被执行。

  2. 传递到IntersectionObserver()构造函数的 options 对象,允许您控制观察者的回调函数的被调用时的环境。我使用时只用了threshold,它可以有以下字段:

root

指定根(root)元素,用于检查目标的可见性。必须是目标元素的父级元素。如果未指定或者为null,则默认为浏览器视窗。

rootMargin

根(root)元素的外边距。类似于 CSS 中的 margin 属性,比如 "10px 20px 30px 40px" (top, right, bottom, left)。如果有指定root参数,则rootMargin也可以使用百分比来取值。该属性值是用作root元素和target发生交集时候的计算交集的区域范围,使用该属性可以控制root元素每一边的收缩或者扩张。默认值为0。

threshold

可以是单一的number也可以是number数组,target元素和root元素相交程度达到该值的时候IntersectionObserver注册的回调函数将会被执行。如果你只是想要探测当target元素的在root元素中的可见性超过50%的时候,你可以指定该属性值为0.5。如果你想要target元素在root元素的可见程度每多25%就执行一次回调,那么你可以指定一个数组[0, 0.25, 0.5, 0.75, 1]。默认值是0(意味着只要有一个target像素出现在root元素中,回调函数将会被执行)。该值为1.0含义是当target完全出现在root元素中时候 回调才会被执行。

intoView() {
            this.$nextTick(()=>{
                const items = document.querySelectorAll(".service-item-icon")
                const io = new IntersectionObserver(entries => {// step1:创建一个 IntersectionObserver对象,并传入相应参数和回调用函数
                    entries.forEach(entry => {
                        try{
                            if(entry.intersectionRatio > 0) {
                                io.unobserve(entry.target) // 移除当前元素的监听器,实现上报过的不再次上报。
                                someFunction() // 执行一些逻辑
                            }
                        }catch(e){
                            throw e
                        }
                    })
                }, {
                    threshold: [0.1]  // options。回调函数将会在目标(item)元素和父元素的交集大小超过阈值10%时候被执行。
                })
                items.forEach(node => { 
                    io.observe(node) // 开始观察
                })
            })
        }
当时遇到的困惑:

1:文档中说,当交集发生变化时才会触发callback,但是打印结果却是全量的,为什么?

解答: MDN中写道:回调函数的触发情况有两种:

a. 当目标元素与视窗或其他指定元素发生交集时候执行。

b. Observer第一次监听目标元素的时候。

所以,此处的console打印全量是因为所有的item都开始被observe监听了。

(由于此处的解释和阮一峰老师的说法有差异,产生了一些误解,但实验结果表明,mdn解释的是符合现象的。)

阮:


image.png

你可能感兴趣的:(IntersectionObserver API使用方法)