元素进入可视区,执行回调的需求
今天遇到了一个特别的需求,及在社区论坛app中,帖子从上往下加载。每次加载的10条,每个帖子为独立元素
当它出现在可视区域内,执行事件上报(这条帖子被浏览了),上报事件只执行一次,不重复触发!
思考很久,因为内嵌在app里面的一个前端web页面,顶部关闭按钮是原生提供的,无法使用页面关闭时,
执行事件上报一共请求了多少条数据!
考虑给每个元素添加监听事件,以后台提供的id 给元素动态添加唯一id,再id开头以xxx,作为标识,
然后通过let ids = document.querySelectorAll("[id^='xxxx']") 拿到一xxx开头的元素,给每个元素
添加监听,移除监听事件,但感觉特别麻烦,给否定了!
后来了解到 web api 有一个Intersection Observer 接口提供了一种异步观察目标元素与其祖先元素
或顶级文档视窗(viewport)交叉状态的方法。祖先元素与视窗(viewport)被称为根(root)。
IntersectionObserver.observe()使IntersectionObserver开始监听一个目标元素。
IntersectionObserver.unobserve()使IntersectionObserver停止监听特定目标元素。
IntersectionObserver.disconnect()使IntersectionObserver对象停止监听工作。
通过intersectionRatio可以看到目标元素现在的可见比例
目标元素在我们的范围内可见,及intersectionRatio它大于0
、、该方法写在vue当中
// 帖子浏览量埋点统计,没出现一个帖子,上报一次
func(){
this.$nextTick(()=>{
let observer = new IntersectionObserver((entries) =>{
entries.forEach((entry)=>{
// 当前有多少目标元素在我们的范围内可见,所以如果它大于0
if (entry.intersectionRatio > 0) {
console.log('出现在可视窗口')
// 执行埋点
const {
aplus_queue} = window;
aplus_queue.push({
action: 'aplus.record',
arguments: ['mt_post_page_views', 'CLK', {
action: 'view',
target: '推荐',
}],
});
// 如果监听过后不再监听,在此回调中清除元素,entry.target代表清除目标dom节点
observer.unobserve(entry.target)
}
})
})
// dynamic_content2 ,需要监听的元素都用这个class
let list = document.querySelectorAll(".dynamic_content2")
// list 拿到时是一个伪数组,需要转化为数组,才能调用数组api
list = Array.prototype.slice.call(list)
// 因为帖子每次往后追加10条,所以下次调用函数只取最后10条添加监听
list = list.slice(-10)
list.forEach((section)=>{
observer.observe(section)
})
})
},