滾動上報實現

  • 2019 年 12 月 4 日
  • 筆記

最近產品說要在一個課程卡片列表頁面中收集用戶滾動行為的數據,大致是要獲取用戶滾動列表後曝光過的課程卡片數據。

scroll

那還不簡單,直接監聽列表元素的scroll事件,然後上報唄:

$list.on('scroll', () => {    let itemHeight = $list.find('li').outerHeight(true);    let scrollTop = $list.scrollTop();    let count = Math.ceil(scrollTop/itemHeight);      // report count...  });

想必聰明的你一看就知道有點問題:

  • scroll事件觸發的那麼頻繁,儘管加上節流也上報了很多次無用數據
  • 首屏的列表卡片曝光個數並沒有上報,需要額外地手動觸發一次scroll事件

beforeunload

為了避免不必要的上報,我想只在頁面卸載的時候上報一次數據應該就可以了吧,於是我就嘗試了beforeunload事件:

let maxCount = 0;    // scroll to change maxCount...    window.addEventListener('beforeunload', () => {    // report maxCount...  });

經過實踐,在QQ客戶端的內嵌頁面可能長時間都不會關閉,上報點依舊不可控。

blur?

思前想後,還是在上報次數上折中,決定嘗試失焦事件。

但是依據MDN的blur event文檔,它是不冒泡的,而如果要在列表元素上監聽焦點相關的事件,是需要在元素上增加tabIndex屬性的,在個別瀏覽器的實現中,對於此種容器元素獲取焦點會有邊框特效,帶來副作用,而且聚焦的範圍也縮小了。

所以採用focusout事件是一個較為不錯的選擇:

let maxCount = 0;  let reportedCount;    // scroll to change maxCount...    $(document.body).on('focusout', () => {    if (maxCount > reportedCount) { // 只需上報最大值即可        // report maxCount...    }  });

focusout事件的兼容性還是不錯的,因為此需求只需要在QQ內嵌頁中完成,所以並沒有考慮到firefox的兼容性,並且它是冒泡的。

總結

以上是本人在此需求點上的一些淺見,如果聰明的你有更好的實踐或者方法的話歡迎指教~

作為前端開發者,系統性地學習DOM,加深對它的理解才更好地在業務實踐中抉擇。

Tags: