大家好,有点我是击事件林三心,用最通俗易懂的让监话讲最难的知识点是我的座右铭,基础是听页进阶的前提是我的初心~
如果在做某个平台的时候,我们需要统计用户点击的有点次数,点击的击事件区域,点击元素,让监等等,听页那我们应该怎么去做比较合适呢?
举个例子,有点我想在用户点击页面上的每一个元素时,我都能把这个元素的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....}
但是一个页面中,点击事件非常多啊,不可能每一个事件中去插入这个函数,非常麻烦
最好的办法就是把 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 = '' }) => { 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,);
其实上面就是埋点库中,全局点击上报的一种解决方案,看似小问题,但是其实面试了这么多人,感觉只有很少一部分人能回答的比较好~
我是林三心
(责任编辑:热点)
松景科技(01079.HK)发布公告:中期净亏48.7万美元 同比收窄63.66%
长三角铁路春运预计发送旅客5000万人次 日均发送旅客125万人次
大众交通(600611.SH)成功发行10亿元超短期融资券 票面年利率3.05%
中国石油首口设计超九千米深井开钻 向超深层储藏探索迈出坚实一步
龙源电力(00916.HK)公布消息:完成发行20亿元短期融资券
Palantir(PLTR.US)盘前大跌12% Q4每股亏损0.08美元