何璇

2017-05-30 23:14

滚动上报实现

本文作者:IMWeb 何璇 原文出处:IMWeb社区 未经同意,禁止转载

最近产品说要在一个课程卡片列表页面中收集用户滚动行为的数据,大致是要获取用户滚动列表后曝光过的课程卡片数据。

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

1条评论

    您需要 注册 一个IMWeb账号或者 才能进行评论。