前言

之所以是用这个Api,主要是为了优化项目。这个不光是可以用来实现图片的懒加载,还特别契合用于项目中的埋点。

优化之前:在页面加载以后获取元素节点的位置+滚动方式来做的。缺点显而易见,代码量比较多,而且监听scroll滚动官方也不推荐,非常影响性能。

优化之后:统一封装Class类,全局统一存储并处理createIntersectionObserver的监听。封装以后可以实现,横向滚动以及竖向滚动到可视区内都可以做到精准埋点。

使用方法在这里插入图片描述

options的三个属性:

  • thresholds:是一个数组,比如你可以设置[0.2,0.5,1]那么在视口区域相交部分达到20%、50%、100%都会触发监听。
  • initialRatio:默认是0,这个参数基本不用改动的。
  • observeAll:这个属性主要是用来监听多个类名一样的数据

IntersectionObserver 4个的方法

  • relativeTo:以你选中的节点作为容器区域,并根据你传入的节点类名进行监听,当传入的类名出现在容器内就会触发。
  • relativeToViewport:以你传入的选择器节点只要出现在视口区域就会触发监听。
  • observe:传入需要监听的类名,回调函数 callback 包含一个参数 result
  • disconnect:取消监听,隐藏或者卸载可取消监听。

vue3-代码示例

vue3中因为没有this,使用getCurrentInstance()

代码封装:

class ScrollObserver {
    #instance;
    #listeners;
    constructor() {
        this.#instance = getCurrentInstance();
        this.#listeners = {};
    }
    static createObserver(selector, thresholds, observeAll = false) {
        // 存在已经有的类名,则会报错,需要先取消监听
        if (this.#listeners[selector]) this.#listeners[selector].disconnect();
        this.#listeners[selector] = uni.createIntersectionObserver(this.#instance, {
            thresholds,
            observeAll,
        });
        return this.#listeners[selector];
    }
    on(selector,callback,observeAll = false) {
    	// 这里的监听[]可根据业务情况自行调整,监听满足条件是会重复触发
        this.constructor.createObserver(selector, [0, 0.2, 1], observeAll)
            .relativeToViewport({ right: 10 })
            .observe(selector, (res) => {
                callback(res);
            });
    }
    // 取消
    off(selector){
        if (!this.#listeners[selector]) return
        this.#listeners[selector].disconnect();
        Reflect.deleteProperty(this.#listeners, selector);
    }
}

margins: 用来扩展(或收缩)参照节点布局区域的边界
这里margin我是用的,{ right: 10 }。按照正常理解应该是当元素滑动到可视区域bottom以下才对,不过这个bottom是距离下边界的距离,相当于还是在元素内部。实际开发也可以修改参数进行微调测试。

使用示例:

// 实例化对象
const emitter = new ScrollObserver();
emitter.on('.example', (res) => {
     if (res.intersectionRatio === 1) {// 业务代码 }
     if (res.intersectionRatio === 0) {// 业务代码}
 });

存在的问题

  • 微信小程序:可以使用scss >>> 穿透语法实现组件的类名监听
  • 支付宝小程序:不可以使用 >>>,目前没有更好的办法兼容,官方推荐使用this.createIntersectionObserver,不过vue3并没有this。
  • 对已存在监听的类名,方法会抛出错误,需要先取消监听,然后再重新创建。
  • 页面的onhide或者onshow以后,虽然是出现在了当前可视区域,这种情况是没有触发监听的。

总结

在小程序开发中,使用这个Api来实现埋点的数据上报,基本是相当精准的,而且不会对性能造成影响。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐