从这里学习哒列表页曝光埋点实现
/**
* 曝光计算
* @param comp 组件实例用来传发埋点记录的数据
* @param headHeight 页面原始头部高度
* @param stickyHeadHeight 页面上滑后吸顶部分+头部的高度
* @param rowHeight 每个列表项的高度
*/
const windowInnerHeight = window.innerHeight; //减少回流
export function scrollShowLog(comp:any,headHeight:number,stickyHeadHeight:number,rowHeight:number){
let lastActive:Array<number> = []; //上次活跃的行
let deActive:Array<number> = []; //非活跃的行
let halfRow = scrollHead - rowHeight/2;
return function(e:{y:number},refresh:boolean){
const { y:scrollY } = e;
/**
* @param e 列表滚动高度
* @param refresh 是否刷新
*/
if(refresh){
lastActive=[];
deActive=[];
}
//计算可见区域的高度
let visibleHeight = windowInnerHeight - (scrollY>scrollHead?headHeight+scrollY:stickyHeadHeight);
//计算当前页面显示的行数,采用四舍五入的原则
let rowCount = Math.round(visibleHeight / rowHeight)
/**
* 当前页面第一行的index
*/
let index = scrollY>halfRow?0:Math.round(-scrollY/rowHeight)-1;
/**
* 当前页面显示的行
*/
let _active:Array<number> =[];
for(let i = 0;i<rowCount;i++){
_active.push(index+i)
}
/**
* 需要上报的行,去除之前上次活跃过的行,包括之前从屏幕消失的行
* 此处注意Array.prototype.includes的兼容性,使用polyfill
*/
let active = _active.filter(
v => !lastActive.includes(v) || deActive.includes(v)
)
/**
* 不活跃的行,0-index-1的行
*/
deActive = [];
for(let i = 0;i<index;i++){
deActive.push(i)
}
/**
* 上次活跃的行,用来避免重复上报,不活跃的行+当前页面显示的行
*/
lastActive = deActive.concat(_active);
/**
* 发埋点
*/
let { xxx } = comp.props; //需要记录的数据
sendShowLog(active,xxx); //发埋点
}
}
使用
componentDidMount(){
this.scrollLog = scrollShowLog(this,x,y,z);
//我是只在滑动结束后记录,避免用户快速上滑产生的无效埋点,使用了better-scroll
this.bScroll.on('scrollEnd',this.scrollLog);
}
一点点问题
在页面筛选条件变化后,列表会刷新,所以需要重置曝光埋点中的不活跃的行deActive
和上次活跃的行lastActive
,并重新发送首屏的埋点
在页面数据请求成功后需,使用下面的方法进行刷新
ps:我的项目中列表刷新会回到页面顶部,所以传了y=0哈~
this.scrollLog({y:0},true)
又一个血的教训
发埋点的时候判断一下数据有没有
在页面实际列表项小于页面可容纳列表项的时候会报错