目录
  • 前言
  • 使用
    • 一、利用IntersectionObserver构造函数创建一个观察器实例
      • 实例属性:
    • 二、观察器实例监听元素相交
      • 三、观察器回调函数参数
        • 回调参数属性:
          • 四、观察器的实例方法
            • 五、总结

            前言

            作为一个前端搬砖仔,偶尔会遇到关于视窗的问题…

            其中就经常会遇到一些数据上报问题,比如某某组件是否被用户看到了,如果看到就要上报数据,让产品同学方便进行数据分析。

            分析这个场景可以发现,必须要用户看到了我才能上报,怎么判断用户是否看到了这个组件呢?

            传统的方法是操作dom,通过这些数据或方法(offsetTop、scrollTop,getBoundingClientRect)来进行比较。

            频繁的对DOM状态的计算,会造成不小的性能损耗,导致页面卡顿。

            接下来介绍一种我最近比较常用的新方式:Intersection Observer(交叉观察器)

            Intersection Observer 翻译过来即交叉观察器

            主要是用于监听目标元素与指定的元素视窗是否发生交叉

            一句话总结:Intersection Observer API 提供了一种异步检测目标元素与祖先元素或 viewport 相交情况变化的方法。 – MDN

            使用

            一、利用IntersectionObserver构造函数创建一个观察器实例

             <template>
              <div class="home"></div>
            </template>
            <script>
            export default {
              name: "HomeView",
              mounted() {
                // 可见性发生变化后的回调
                function callback() {
                  console.log("触发了");
                }
                // 交叉观察器配置项
                let options = {};
                // 生成交叉观察器
                const observer = new IntersectionObserver(callback);
              },
            };
            </script>
            

            (callback是当元素可见比例超过指定阈值后会调用的一个回调函数,options是一个可以用来配置 observer 实例的对象。)

            输出一下IntersectionObserver构造函数返回的实例

            Intersection Observer交叉观察器示例解析

            实例属性:

            root:root 属性用来获取当前 intersectionObserver 实例的根元素,用于判断元素是否可见区域。

            (注:这个既可以是 target 元素祖先元素也可以是指定 null 则使用浏览器视口 做为容器 (root)。)

            rootMargin:一个类似于margin的字符串参数,就可以使用 root margin 来调整根矩形大小。

            (注:由于使用Intersection Observer的过程中所有区域均被当做一个矩形看待,因此当我们需要调整元素边界的矩形时,用 root margin 来调整大小。)

            threshold:阈值,可以传一个0 ~ 1的number,也可以传个0 ~ 1范围的number数组。

            (注:如果传一个0 ~ 1的number,如0.5则说明,目标元素和root相交超过50%时,即二者重合超过目标元素的50%时,触发回调,如果是一个数组[0.1, 0.2, 0.5]则分别在10% 20% 50%处触发回调)

            二、观察器实例监听元素相交

            <template>
              <div class="home">
                <div id="target" class="target-item"></div>
              </div>
            </template>
            <script>
            export default {
              name: "HomeView",
              mounted() {
                // 可见性发生变化后的回调
                function callback(data) {
                  console.log("触发了");
                  console.log(data);
                }
                // 交叉观察器配置项
                let options = {};
                // 生成交叉观察器
                const observer = new IntersectionObserver(callback);
                // 获取目标节点
                let target = document.getElementById("target");
                // 监听目标元素
                observer.observe(target);
              },
            };
            </script>
            <style scoped>
            .home {
              height: 300vh;
            }
            .home .target-item {
              margin-top: 120vh;
              width: 20px;
              height: 20px;
              background: #000;
            }
            </style>
            

            可以看到

            Intersection Observer交叉观察器示例解析

            通过滚动,可以不停监听到观察器的回调。

            三、观察器回调函数参数

            看到在观察器的回调中是返回了一个对象的,修改原来的回调函数,对应看看到底返回了啥?

            export default {
              name: "HomeView",
              mounted() {
                // 可见性发生变化后的回调
                function callback(data) {
                  console.log("触发了");
                  data.map((item) => {
                    // 目标元素的getBoundingClientRect的返回值。
                    console.log(item.boundingClientRect);
                    // 目标元素和根元素交叉区域的getBoundingClientRect的返回值。
                    console.log(item.intersectionRatio);
                    // 目标元素的可见比例,相当于二者重合了多少。
                    console.log(item.intersectionRect);
                    // 目标元素与根元素是否相交
                    console.log(item.isIntersecting);
                    // 根元素的getBoundingClientRect的返回值
                    console.log(item.rootBounds);
                    // 目标元素,是个dom
                    console.log(item.target);
                    // 从首次创建观察者到触发指定阈值发生交叉的时间
                    console.log(item.time);
                  });
                }
                // 交叉观察器配置项
                let options = {
                  threshold: 0.5,
                };
                // 生成交叉观察器
                const observer = new IntersectionObserver(callback, options);
                // 获取目标元素
                let target = document.getElementById("target");
                // 监听目标元素
                observer.observe(target);
              },
            };
            

            可以看到控制台输出了下述内容:

            Intersection Observer交叉观察器示例解析

            可以看到返回了很多东西

            其中就有我们熟悉的元素的getBoundingClientRect属性。

            回调参数属性:

            boundingClientRect: 对象,返回了目标元素的getBoundingClientRect的返回值。

            intersectionRatio:对象,返回了目标元素和根元素交叉区域的getBoundingClientRect的返回值。

            intersectionRect: 数字,目标元素的可见比例,相当于二者重合了多少。

            isIntersecting: 布尔值,目标元素与根元素相交是否相交

            (如果相交,则返回 true ,若为true则说明至少到达了一个阈值,如果为false,说明目标元素在阈值范围内不可见)

            rootBounds: 对象,返回了根元素的getBoundingClientRect的返回值。

            target:对象,目标元素,是个dom

            time: 数字,从首次创建观察者到触发指定阈值发生交叉的时间

            因此通过观察器的回调参数可以做到精确监听目标的,通过这些参数可以更好的支持如下拉加载技术上报等场景,由于该属性是原生api因此比起频繁的操作dom会来的更丝滑。

            四、观察器的实例方法

            通过上文我们已经说明了,如何使用交叉观察器,并介绍了观察器的实例属性及回调参数

            下面说一下观察器的实例方法!

                // 生成交叉观察器
                const observer = new IntersectionObserver(callback, options);
                // 获取目标元素
                let target = document.getElementById("target");
                // 监听目标元素
                observer.observe(target);
            

            可以看到监听目标元素的时候用了 observe 方法,这就是观察器的实例方法之一—— 监听目标元素

            观察器的实例方法一共有四个

            disconnect:停止对所有的目标元素的观察

            observe:监听目标元素(可监听多个)

            takeRecords:返回一个IntersectionObserverEntry对象数组(观察器回调参数就是这个),里面存放的各个目标元素的相交信息

            unobserve:停止对一个指定目标元素的观察

            通过代码来演示下上述方法:

            <template>
              <div class="home">
                <div id="target1" class="target1-item"></div>
                <div id="target2" @click="unobserve()" class="target2-item"></div>
                <div style="margintop: 10px" @click="disconnect">disconnect</div>
              </div>
            </template>
            <script>
            export default {
              name: "HomeView",
              data() {
                return {
                  observer: {},
                };
              },
              mounted() {
                // 可见性发生变化后的回调
                function callback(data) {
                  console.log(data[0].target.id);
                }
                // 生成交叉观察器
                this.observer = new IntersectionObserver(callback);
                // 获取目标元素1
                let target1 = document.getElementById("target1");
                // 获取目标元素2
                let target2 = document.getElementById("target2");
                // 监听目标元素1
                this.observer.observe(target1);
                // 监听目标元素2
                this.observer.observe(target2);
              },
              methods: {
                unobserve() {
                  let target2 = document.getElementById("target2");
                  // 停止监听目标元素2
                  this.observer.unobserve(target2)
                },
                disconnect() {
                  // 停止监听所有目标元素
                  this.observer.disconnect();
                },
              },
            };
            </script>
            

            代码效果如下所示:

            Intersection Observer交叉观察器示例解析

            可以看到一开始是监听元素1和元素2,接着停止元素2的监听,最后停止所有元素的监听

            以上就是Intersection Observer(交叉观察器)的基本使用了。

            五、总结

            (1)利用IntersectionObserver构造函数创建一个观察器实例,设置其回调和基本参数

                // 可见性发生变化后的回调
                function callback() {
                }
                // 生成交叉观察器
                this.observer = new IntersectionObserver(callback);
            

            (2)获取目标元素节点,并监听该元素

            // 获取目标元素
            let target = document.getElementById("target");
            // 监听目标元素
            this.observer.observe(target);
            

            (3)回调中处理相关逻辑

            function callback(data) {
                console.log(data)
            }
            

            (4)观察器使用结束后,取消对元素的监听

            // 停止观察某个目标元素
            observer.unobserve(target);
            // 关闭监视器
            observer.disconnect();
            

            聊聊Intersection Observer各大浏览器的支持性 截图自

            Intersection Observer交叉观察器示例解析

            总的来说,这个还是适用于很多浏览器的。

            各位前端朋友,如果以后有遇到下拉加载或数据上报的场景的话不妨使用一下这个Intersection Observer

            确实是一个开发的好工具。

            以上就是Intersection Observer交叉观察器示例解析的详细内容,更多关于Intersection Observer交叉观察器的资料请关注其它相关文章!

            声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。