背景
页面中会有一些商品模块,数据组提出了一个需求就是统计当前商品曝光的次数,点击购买的次数,最终下单的次数。获取一个下单转化率
分析
1、点击购买次数可以通过点击购买按钮做买单,下单可以通过点击checkout或者是下单成功之后做埋点。
2、曝光埋点就是,当某一个商品模块展示到可视区域之后做一次埋点,当该商品块滑出去之后,用户再次滑到这个模块的时候在做一次统计。
3、如果通过监听页面滚动查看商品模块展示与否的话性能太差,会不停的触发页面的重绘,性能极差。又没有像android那种可以监听某个view出现在可是去的api。经过一通百度发现浏览器有一个api是IntersectionObserver,可以监听元素的曝光,但是整体的兼容性没有那么好,兼容性情况
4、经过考虑我们主要做的是海外市场,chrome的使用率还是很高,先暂时使用这个api
IntersectionObserver介绍
const io = new IntersectionObserver(callback, option)
io.observe(v) // 开始观察
io.unobserve(el) // 停止观察
io.disconnect() // 关闭观察器
IntersectionObserver是浏览器原生提供的构造函数,接受两个参数,callback是可见性变化时的回调函数,option是配置对象可选参数
callback一般会触发两次,一次是目标进入视口,另一次是完全离开视口
var io = new IntersectionObserver(
entries => {
console.log(entries);
}
);
entries 是一个数组,每一个成员都是一个IntersectionObserverEntry对象
IntersectionObserverEntry对象一共有留个属性
{
time: 3893.92,
rootBounds: ClientRect {
bottom: 920,
height: 1024,
left: 0,
right: 1024,
top: 0,
width: 920
},
boundingClientRect: ClientRect {
// ...
},
intersectionRect: ClientRect {
// ...
},
intersectionRatio: 0.54,
target: element
}
- time: 课件性发生变化的时间,一个高精度时间戳,单位为毫秒
- target: 被观察的元素,是一个DOM节点对象
- rootBounds: 根元素的矩形区域的信息,getBoundingClientReact()方法的返回值,如果没有根元素(即直接相对于视口滚动),则返回null
- boundingClientReact: 目标元素的矩形区域信息
- intersectionReact: 目标元素与视口(或者根元素)的交叉区域的信息
- intersectionRatio: 目标元素的可见比例,即intersectionReact占boundingClientReact的比例,完全可见时为1,完全不可见时小于等于0
实现
代码如下
function exposeFn(params) {
let {
nodes,
report,
disReport
} = params
if(!nodes){
console.warn('没有添加要曝光的node节点')
return
}
const intersectionObserver = new IntersectionObserver(entries => {
// console.log(entries);
entries.forEach(entry => {
// console.log('entry.intersectionRatio', entry.intersectionRatio);
if (entry.intersectionRatio > 0) {
// 上报曝光方法
report && report(entry)
} else {
// 将消失在屏幕的元素下掉
disReport && disReport(entry)
}
})
})
nodes.forEach(node => {
intersectionObserver.observe(node)
})
}
export default class Expose {
constructor(props) {
this.from = props.from
this.sections = []
this.intersectionObserver = null
this.init()
}
init() {
let nodes = document.querySelectorAll(".section")
exposeFn({
nodes,
report: this.report,
disReport: this.disReport
})
}
report(entry) {
console.log('report ---->', entry.target.getAttribute('data-section'), entry.intersectionRatio, entry)
}
disReport(entry) {
console.log('disreport ---->', entry.target.getAttribute('data-section'), entry.intersectionRatio)
}
}