滚动上报实现
- 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,加深对它的理解才更好地在业务实践中抉择。