微信小程序列表埋点曝光指南

6,025 阅读2分钟

背景

最近项目中,开发一个小程序列表页,PM大大给我提了一个埋点需求,列表中的每一项,出现在屏幕中的时候,需要上报一条记录。

目标

如图中操作,要依次上报 item 1 - item7,但是上滑的时候,不再重复上报

怎么做

接到需求的第一感觉是,我难道要监听页面滚动,然后通过offsetTop 去算吗!!!??? 这样显然不是最高效的。于是我去翻了一下微信的开发文档,发现有一个 IntersectionObserver 的API,正好满足我的需求。

首先我们需要创建一个 IntersectionObserver wx.createIntersectionObserver(Object component, Object options)

IntersectionObserver 一共有四个方法

  1. IntersectionObserver.relativeTo 使用选择器指定一个节点,作为参照区域之一。
  2. IntersectionObserver.relativeToViewport(Object margins) 指定页面显示区域作为参照区域之一
  3. IntersectionObserver.observeCallback callback) 指定目标节点并开始监听相交状态变化情况
  4. IntersectionObserver.disconnect() 停止监听。回调函数将不再触发

我们这里的参照物是屏幕,所以我们使用IntersectionObserver.relativeToViewport来制定我们的参照物,并制定相较规则

Page({
  data: {
    list: [
      { value: 1, hadReport: false }, 
      { value: 2, hadReport: false },
      { value: 3, hadReport: false },
      { value: 4, hadReport: false },
      { value: 5, hadReport: false },
      { value: 6, hadReport: false },
      { value: 7, hadReport: false },
      { value: 8, hadReport: false },
      { value: 9, hadReport: false },
    ]
  },
  onLoad() {
    this._observer = this.createIntersectionObserver({ observeAll: true })
    this._observer.relativeToViewport({ bottom: 0 })
      .observe('.item', (res) => {
        const { index } = res.dataset;
        if (!this.data.list[index].hadReport) {
          console.log(`report ${index}`) 
          this.data.list[index].hadReport = true;
          this.setData({ list: [].concat(this.data.list)})
        }
        
      })
  },
  onUnload() {
    if (this._observer) this._observer.disconnect()
  }
})

最后实现的效果如下

结论

  1. 类似这样的埋点,我们以后可以采用监听dom的方式去做,而不是一昧的只想着监听滚动计算位置。
  2. 除了可以做埋点上报,这种监听的方式,还是很适合去做一些图片懒加载等一系列操作。

微信小程序代码片段,点击查看

联想

上述的所有操作,都是基于微信小程序去做的,那么浏览器有没有相应的API呢?

浏览器是有相应的API的,Intersection Observer API,具体的用法与上述的用法类似。

  var options = {
    rootMargin: '0px',
    threshold: 1.0
  }

  var observer = new IntersectionObserver((...args) => {
    console.log(args);
  }, options);
  observer.observe(document.querySelector('.item'));

注意这个会监测dom元素的可见性变化,也就是说当dom出现在视窗的时候会触发回调,消失在视窗的时候也会触发回调

但是浏览器的IntersectionObserver属性兼容性一般,如果想要在浏览器做曝光或者懒加载可以考虑采用原始的方法,监听浏览器滚动,并计算dom的offsetTop,可以参考笔者很久前写的图片延时 加载原理 及应用

参考文档