小程序模塊曝光埋點方法

原文鏈接:https://juejin.im/post/5daab2d8f265da5b5b6c754b

 

作者:w_西城

我們在處理模塊曝光埋點時,需要根據頁面滾動的位置判斷模塊是否可見(被曝光)。Web 上傳統方法是增加頁面 scroll 監聽事件,根據滾動位置與模塊位置進行對比判斷,小程序上也可以使用這種方法,但現在有更便捷優雅的替代方案 —— IntersectionObserver 對象。

IntersectionObserver 對象

IntersectionObserver 對象,用於推斷某些節點是否可以被用戶看見,下面將介紹相關的 API:

(1) 創建

通過 this.createIntersectionObserver 創建,該方法可傳入的參數有三個:

  • thresholds:數值數組,代表相交比例的閾值(可有多個,取值範圍[0,1]),當相交到達該閾值時會觸發一次監聽回調,在曝光埋點場景下設置爲中間位置 [0.5] 即可;
  • initialRatio:初始相交比例,如果方法調用時檢測到的相交比例與這個值不相等且達到閾值,則會觸發一次監聽器的回調函數,在曝光埋點的場景下設置爲默認值0即可;
  • observeAll:是否同時觀測多個目標節點;

(2) 設置參考區域

設置參考區域的方法有兩個:io.relativeToViewport()io.relativeTo('selector', { ...margins }),如果判斷相交參考區域是窗口,則使用前者,曝光埋點的場景下就使用這個;後者可用選擇器設置其他節點作爲相交的參考區域。

(3) 監聽

開始監聽方法:io.observe(selector, callback),selector代表目標模塊的選擇器,當它和參考區域相交達到閾值比例時,會觸發 callback 回調函數,回調函數接受如下幾個參數(在該場景中暫時都不會用到):

  • intersectionRatio: 兩者相交比例;
  • time:相交檢測時的時間戳;
  • 各種邊界:
    • intersectionRect:相交區域的邊界;
    • boundingClientRect:目標邊界;
    • relativeRect:參照區域的邊界; 

(4) 取消監聽

當頁面退出時記得要取消監聽:io.disconnect()。

監聽相交區域類

我們可以設計一個類,用來處理監聽相交區域的邏輯。

構造函數

首先來看構造函數,代碼如下:

class IntersectionObserver {
  constructor(options) {
    this.$options = {
      context: null,
      threshold: 0.5,
      initialRatio: 0,
      observeAll: false,
      selector: null,
      relativeTo: null,
      onEach: res => res.dataset,
      onFinal: () => null,
      delay: 200,    
      ...options,
    }
    this.$observer = null
  }
}複製代碼

顯然,構造函數傳入了一些重要的參數,包括 createIntersectionObserver 所需要的三個參數:thresholds, initialRatio, observeAll 和上下文 context ;設置參考區域所需的 relativeTo ;監聽方法所需的目標模塊選擇器 selector

最後還有 IntersectionObserver 類監聽調用時需要的三個參數:

  • onEach:每一次觸發監聽調用時,也會調用 onEach 方法;
  • onFinal:在觸發監聽調用一段時間 delay 後,會調用一次 onFinal 方法。在模塊曝光埋點場景下,如果頁面在快速滾動時,每次的監聽觸發都上報埋點,一時間請求會堆積很多,所以需要 onFinal 方法,在一段時間後統一上報曝光埋點;
  • delay:調用 onFinal 方法的間隔時間;

監聽

要想開始監聽相交區域,需要先創建監聽器,設置完相交區域後再開始監聽,關鍵代碼如下:

_createObserver() {
  const opt = this.$options
  const observerOptions = {
    thresholds: [opt.threshold],
    observeAll: opt.observeAll,
    initialRatio: opt.initialRatio,
  }

  // 創建監聽器
  const ob = opt.context
    ? opt.context.createIntersectionObserver(observerOptions)
    : wx.createIntersectionObserver(null, observerOptions)

  // 相交區域設置
  if (opt.relativeTo) ob.relativeTo(opt.relativeTo)
  else ob.relativeToViewport()

  // 開始監聽
  let finalData = []
  let isCollecting = false   
  ob.observe(opt.selector, res => {
    const { intersectionRatio } = res
    const visible = intersectionRatio >= opt.threshold
    if (!visible) return

    const data = opt.onEach(res)
    finalData.push(data)

    if (isCollecting) return    // 正在收集監聽結果,不會調用 onFinal
    isCollecting = true    

    // 設置延遲調用 onFinal
    setTimeout(() => {
      opt.onFinal.call(null, finalData)
      finalData = []
      isCollecting = false
    }, opt.delay)
  })
  return ob
}
複製代碼

 

對外暴露的公用方法

封裝對外的 _createObserver 方法:

connect() {
  if (this.$observer) return this
  this.$observer = this._createObserver()
  return this
}
複製代碼

 

封裝停止監聽的方法:

disconnect() {
  if (!this.$observer) return
  const ob = this.$observer
  if (ob.$timer) clearTimeout(ob.$timer)
  ob.disconnect()
  this.$observer = null
}
複製代碼

 

使用方法

import IntersectionObserver from './intersection-observer.js';

const ob = new IntersectionObserver({...})
ob.connect()複製代碼

 

詳見代碼片段:developers.weixin.qq.com/s/lqUakfmM7… 

總結

當然,曝光埋點也可以使用傳統 Web 的監聽 scroll 事件的方式。不過,既然小程序提供了 IntersectionObserver API 並且幾乎所有客戶端都已支持,那自然就用這種更方便的方式。

另外,在百度小程序和支付寶小程序上也有支持相關的API,跨端開發也不用考慮其他小程序不支持。

關於兼容性

支付包小程序兼容性有待考證,百度可以使用 IntersectionObserver,不過需要注意 this.createIntersectionObserver 非組件是沒有的,只能使用 swan.createIntersectionObserver(this);第二點,createIntersectionObserver的參數observeAll 需要改成 selectAll (百度小程序代碼片段:swanide://fragment/142c0f60156b1e850dc239553ecffe7b1571810456384)。

參考文檔

  1. 官方文檔
  2. 談談IntersectionObserver懶加載(Web API 表現形式詳解,和小程序上相同);
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章