咱們在處理模塊曝光埋點時,須要根據頁面滾動的位置判斷模塊是否可見(被曝光)。Web 上傳統方法是增長頁面 scroll 監聽事件,根據滾動位置與模塊位置進行對比判斷,小程序上也可使用這種方法,但如今有更便捷優雅的替代方案 —— IntersectionObserver 對象。javascript
IntersectionObserver 對象,用於推斷某些節點是否能夠被用戶看見,下面將介紹相關的 API:html
經過 this.createIntersectionObserver
建立,該方法可傳入的參數有三個:java
[0,1]
),當相交到達該閾值時會觸發一次監聽回調,在曝光埋點場景下設置爲中間位置 [0.5]
便可;設置參考區域的方法有兩個:io.relativeToViewport()
和 io.relativeTo('selector', { ...margins })
,若是判斷相交參考區域是窗口,則使用前者,曝光埋點的場景下就使用這個;後者可用選擇器設置其餘節點做爲相交的參考區域。小程序
開始監聽方法:io.observe(selector, callback)
,selector表明目標模塊的選擇器,當它和參考區域相交達到閾值比例時,會觸發 callback 回調函數,回調函數接受以下幾個參數(在該場景中暫時都不會用到):api
當頁面退出時記得要取消監聽:io.disconnect()。數組
咱們能夠設計一個類,用來處理監聽相交區域的邏輯。bash
首先來看構造函數,代碼以下:ide
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 類監聽調用時須要的三個參數:post
onEach
方法;delay
後,會調用一次 onFinal
方法。在模塊曝光埋點場景下,若是頁面在快速滾動時,每次的監聽觸發都上報埋點,一時間請求會堆積不少,因此須要 onFinal
方法,在一段時間後統一上報曝光埋點;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)。