前言大家好,我是林三心,用最通俗易懂的话讲最难的知识点是我的座右铭,基础是进阶的前提是我的初心~
背景如果在做某个平台的时候,我们需要统计用户点击的次数,点击的区域,点击元素,等等,那我们应该怎么去做比较合适呢?
举个例子,我想在用户点击页面上的每一个元素时,我都能把这个元素的DOM节点信息记录下来,并且上报到服务器,便于后面产品那边的统计用户喜好~
公共函数?处处调用?那我们要怎么去做呢?写一个公共函数吗?然后去统一做上报吗?
我首先写一个函数,这是一个获取点击元素信息的函数,我们可以在点击的 event 参数中拿到目标元素 target
文章插图
图片
const reportDOM = (e: PointerEvent) => {// 获取到点击的目标元素const el = e.target// 把目标元素解析成字符串const detAIl = htmlElementAsString(el)// 进行上报report(detail)}// 上报函数export const report = (detail) => {request(url, detail)}// 解析函数export function htmlElementAsString(target: HTMLElement): string {const tagName = target.tagName.toLowerCase();if (tagName === 'body') {return '';}let classNames = target.classList.value;classNames = classNames !== '' ? ` class='${classNames}'` : '';const id = target.id ? ` id="${target.id}"` : '';const innerText = target.innerText;return `<${tagName}${id}${classNames !== '' ? classNames : ''}>${innerText}</${tagName}>`;}
【让你监听页面所有点击事件,你会怎么做?】写完这几个函数之后,我们只需要在每一个点击事件中去插入这个函数即可const click1 = (e: PointerEvent) => {reportDOM(e)// coding....}const click2 = (e: PointerEvent) => {reportDOM(e)// coding....}const click3 = (e: PointerEvent) => {reportDOM(e)// coding....}
但是一个页面中,点击事件非常多啊,不可能每一个事件中去插入这个函数,非常麻烦全局监听 + elementFromPoint基本做法最好的办法就是把 click 事件挂载在 window 身上,然后根据 elementFromPoint 去计算坐标匹配的元素,进行解析上报
window.addEventListener('click',(e: PointerEvent) => {// 通过坐标计算出目标元素const el = getTargetDomByPointerEvent(e);if (!el) return;// 把目标元素解析成字符串const detail = htmlElementAsString(el);// 进行上报report(detail);},true,);// 通过坐标计算目标元素export const getTargetDomByPointerEvent = (e: PointerEvent) => {const el = document.elementFromPoint(e.pageX, e.pageY);if (el) {return el as HTMLElement;}return null;};
拓展做法,只上报所需元素我们可以通过配置一个数组 globalClickListeners ,只对我们所需要的 DOM 节点进行监听上报,const globalClickListeners = [{selector: '.cla', // 选择器},{elementText: 'report2', // 元素文本},{selector: '.r', // 选择器 + 元素文本elementText: 'report3',},];
那么我们需要对 window 的点击监听进行改造window.addEventListener('click',(e: PointerEvent) => {const el = getTargetDomByPointerEvent(e);if (!el) return;if (globalClickListeners.length) {globalClickListeners.forEach(({ selector, elementText, data = https://www.isolves.com/it/cxkf/bk/2023-08-28/'' }) => {if (selector) {// 选择器的情况const els = document.querySelectorAll(selector);// 点击元素是否包含所属选择器范围const isIncludes = [...(els as unknown as any[])].includes(el);// 包含则上报if (isIncludes) {const detail = htmlElementAsString(el);// 进行上报report(detail);}} else if (el.textContent === elementText) {// 文本相同情况const detail = htmlElementAsString(el);// 进行上报report(detail);}});}},true,);
小结其实上面就是埋点库中,全局点击上报的一种解决方案,看似小问题,但是其实面试了这么多人,感觉只有很少一部分人能回答的比较好~结语我是林三心
- 一个待过小型toG型外包公司、大型外包公司、小公司、潜力型创业公司、大公司的作死型前端选手;
- 一个偏前端的全干工程师;
- 一个不正经的掘金作者;
- 逗比的B站up主;
- 不帅的小红书博主;
- 喜欢打铁的篮球菜鸟;
- 喜欢历史的乏味少年;
- 喜欢rap的五音不全弱鸡
推荐阅读
- EasyNetQ库:让你的分布式系统消息开发快人一步!
- 如何逼自己瘦下来?这8个方法让你一个月瘦20斤
- word页面颜色怎么设置 word页面颜色怎么设置方法
- 科学瘦身5步走:让你不再为体重增长烦恼!
- 脂肪都怕的10种碱性食物,让你越吃越瘦
- 从135瘦到95斤,让你瘦下来的8个方法,瘦出自信和活力
- 是什么决定,让你瞬间从国企辞职呢?
- 2023一集就封神的6部国产剧,每部都是王炸,哪部让你意犹未尽?
- 减肥一定要提高代谢,8个方法让你养成易瘦体质,不再反弹
- word怎么截图整个页面 word怎么截图