滾動上報實現
- 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,加深對它的理解才更好地在業務實踐中抉擇。

