今天小编跟大家讲解下有关前端埋点之曝光实现 ,相信小伙伴们对这个话题应该有所关注吧,小编也收集到了有关前端埋点之曝光实现 的相关资料,希望小伙伴们看了有所帮助。
最近有一个工作需求是曝光埋点 让我得以有机会接触相关的东西。之前实习时没有做过这方面的需求 个人项目更是和埋点扯不上关系。以至于上周开会讨论时听到“埋点”这个词就怂了。
不过后面听大佬分析了下后才意识到 原来“埋点”是这个意思。曝光埋点的思路也是很简单:无非是判断某个DOM是否出现在视窗中 出现了就收集数据上报给服务端。
所谓“埋点” 是数据采集领域(尤其是用户行为数据采集领域)的术语 指的是针对特定用户行为或事件进行捕获、处理和发送的相关技术及其实施过程。比如用户某个文章点击次数、观看某个视频的时长等等。再说「曝光埋点」 它与「图片懒加载」「计算广告浏览量」这些需求一样 本质就是让你计算某一元素和另一元素(视窗)的相对可视状态/相对位置 然后进行一些操作(一般是上报给服务端)。
思考如何实现最先出现在脑海里的方法是利用getBoundingClientRect/offset类+onscroll。即:注册滚动事件 然后在滚动的回调函数中利用getBoundingClientRect/offset类拿到每个元素的位置信息 然后经过判断确定是否元素处于曝光状态/视窗中。
但这种方式有很大的缺陷。如果你熟悉浏览器的渲染过程的话 就会知道调用getBoundingClientRect/offset类会引起浏览器的回流重绘 影响网页表现/性能。频繁、大量调用更不是一个妥当的选择。
我开始尝试在社区找找看有没有其他更妥当的方法 还真被我找到了:Intersection Observer
Intersection Observer它提供了一种异步观察目标元素与祖先元素或顶级文档Viewport的交集变化的方法。也就是说 不仅可以用来获得相对于视窗的曝光 可以做得更多 这取决于“另一个元素”是什么。
Intersection Observer将本来是开发者做的:监听滚动、遍历获取元素与另一个元素(或视窗)相对位置的工作给做了。这两块工作是页面性能损耗大户 现在交给浏览器来实现 会比我们开发者来做要妥当的多。开发者现在只需要关心其他业务逻辑即可
那这么好用的API 它的兼容性状况如何呢
还不错 但兼容性方面要求高的话还是不能让人放心使用。
Polyfill
但不用担心 我们有polyfill。W3C提供了一个polyfill 当浏览器不支持时使用常规解决方案替代。它的思路就是在检测到当前浏览器不支持Intersection Observer API时 使用getBoundingClientRect去重新实现一遍Intersection Observer API。
那么使用了该Polyfill后 浏览器兼容性状况如何呢
非常棒! (IE7都支持了 还想啥呢 大兄弟。)
曝光实现步骤思路就像上面一再提到的 很简单:
new IntersectionObserver()实例化一个全局observer (结合vue指令)让每个DOM自行把自己加入到observer的观察列表。当某个DOM进入视窗 收集对应的信息 上报。取消对该DOM的观察。代码实现Exposure.ts 封装成类
import 'intersection-observer';export default class Exposure { private observer: IntersectionObserver | undefined; constructor() { this.init(); } private init() { const self = this; this.observer = new IntersectionObserver( (entries, observer) => { entries.forEach(item => { if (item.isIntersecting) { const data = item.target.getAttribute('data-article'); self.upload(data); observer!.unobserve(item.target); } }); }, { root: null, rootMargin: '0', threshold: 0.1, } ); } public add(el: Element) { this.observer && this.observer.observe(el); } private upload(data: string | null) { if (data) { // ajax上报数据 } }}directive/exposure.ts 封装vue指令
import Exposure from '@/lib/Exposure';import vue from 'vue';const exposure = new Exposure();vue.directive('exposure', { bind(el) { exposure.add(el); },});*.vue 使用指令
<div v-exposure :data-article='article'>...</div>原文:https://segmentfault.com/a/1190000021446921来源:爱蒂网