可视化埋点平台元素曝光采集intersectionObserver的方法是什么
这篇文章主要介绍“可视化埋点平台元素曝光采集intersectionObserver的方法是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“可视化埋点平台元素曝光采集intersectionObserver的方法是什么”文章能帮助大家解决问题。
设计方案
为了快速上线第一版,笔者最初的设计方案为:
根据服务端返回的 xpath,寻找到对应的 dom 元素,对元素进行 observe
监听 dom 变更事件,当 dom 发生改变后,重新根据 xpath 寻找 dom 元素,对元素进行再次 observe
在该方案中,存在几个触发时机可能导致的问题:
当监听发生在元素渲染到页面后,首次监听的同时,是否会触发回调(影响到初次曝光的准确性)
多次监听同一 dom 元素,是否会多次触发回调(影响到 dom 变更,多次监听同一元素后,曝光的准确性)
测验结论
当初次监听元素时,会立即触发一次回调
多次监听同一元素,并不会多次触发回调
在上述逻辑成立的情况下,笔者最初的方案其实是可以正常工作,对于初次曝光,虽然发生在元素渲染到 dom 之后,但是由于会立即触发一次,故初次曝光能够正常上报。而当 dom 发生变更后,消失的元素,虽然没有调用 unobserve,但是由于该元素消失了,并不会影响后续曝光埋点的上报,所以并没有带来大的问题,而 dom 变更后,元素如果依然存在,虽然再次进行了监听,但是多次监听并不影响同一元素,所以其实也没有问题。
对于第一版,上线后也确实能够正常工作,但是对于没有 unobserve 这一点,由于 js 的垃圾回收机制,必须是没有引用后才会销毁,而没有 unobserve,那么内部必然会维护一份监听的元素的列表,保留了已经从 dom 中移除的元素的引用,从而造成内存泄漏。
故需要做一些策略来避免该问题(不然代码也会被吐槽),思路如下:
维护一份 xpath -> 元素的映射,当 dom 发生变更时,遍历所有 xpath 寻找对应的元素,
如果元素同映射中一致,那么表示该元素没有发生变更,此时可以直接忽略,什么都不做。
而如果元素发生变化,那么调用 unobserve 取消旧元素的监听,同时对新元素进行监听即可。
完整的伪代码
// 工具函数命名很清晰,含义不赘述import { getEleByXpath, getXpathByEle, debounce } from 'utils'; class track { constructor() { this.config = {} // 存储远程服务端返回的埋点 xpath 信息 this.map = {} // 维护的 xpath -> el 映射 this.observer = null; // intersectionObserver 实例 } // 远端获取需要曝光点的元素 getConfig() { return fetch('xxx').then(res => { this.config = res; this.config.forEach(item => { // 初始化 xpath -> el 映射 this.map[item.xpath] = null; }) }); } // 监听 dom 变更 addDomtreeMutatorObserver() { // 不关心属性变化 const config = { attributes: false, childList: true, subtree: true }; // 监听dom变更,消个抖 const observer = new MutationObserver(debounce(this.observe.bind(this), 200)); observer.observe(document.body, config); } // 监听元素曝光 observe() { // 此处可以加个 requestIdleCallback 来增强性能 this.config.forEach((item) => { const targetEl = getEleByXpath(item.xpath); // 新旧元素不一致才需要取消旧元素监听,增加新元素监听 if (targetEl !== this.map[item.xpath]) { // 元素存在,就监听 if (targetEl) { this.observer.observe(targetEl); } // 取消旧元素的监听 if (this.map[shadow.xpath]) { this.observer.unobserve(this.map[shadow.xpath]); } // 更新map中的el this.map[shadow.xpath] = targetEl; } // 一致,则什么都不做 }); } // 创建 intersectionObserver initObserver() { const callback = (entries) => { entries.forEach((entry) => { if (entry.intersectionRatio > 0.2) { const targetXpath = getXpath(entry.target); for (let i = 0; i < this.config.length; i++) { if (this.config[i].xpath === targetXpath) { // xpath一致 // 发送曝光埋点 } } } }); }; const observer = new IntersectionObserver(callback, { threshold: 0.2, }); this.observer = observer; } init() { this.getConfig().then(() => { // 初始化 intersectionObserver this.initObserver(); // 监听元素 this.observe(); // 监听 dom 元素变更 this.addDomtreeMutatorObserver(); }); }}
关于“可视化埋点平台元素曝光采集intersectionObserver的方法是什么”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注编程网行业资讯频道,小编每天都会为大家更新不同的知识点。
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341