本文作者:IMWeb 何璇 原文出处:IMWeb社区 未经同意,禁止转载
最近产品说要在一个课程卡片列表页面中收集用户滚动行为的数据,大致是要获取用户滚动列表后曝光过的课程卡片数据。
那还不简单,直接监听列表元素的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
事件:
let maxCount = 0;
// scroll to change maxCount...
window.addEventListener('beforeunload', () => {
// report maxCount...
});
经过实践,在QQ客户端的内嵌页面可能长时间都不会关闭,上报点依旧不可控。
思前想后,还是在上报次数上折中,决定尝试失焦事件。
但是依据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,加深对它的理解才更好地在业务实践中抉择。