2023-08-28 10:18:05來源:前端之神
大家好,我是林三心,用最通俗易懂的話講最難的知識點是我的座右銘,基礎是進階的前提是我的初心~
背景如果在做某個平臺的時候,我們需要統計用戶點擊的次數,點擊的區域,點擊元素,等等,那我們應該怎么去做比較合適呢?
(資料圖片)
舉個例子,我想在用戶點擊頁面上的每一個元素時,我都能把這個元素的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 = "" }) => { 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的五音不全弱雞關鍵詞:
前言大家好,我是林三心,用最通俗易懂的話講最難的知識點是我的座右銘
前言4G的機器上申請8G的內存,是否可以成功?這個問題沒有辦法,是沒有
VisualStudioCode是一款功能強大、可擴展且輕量級的代碼編輯器,經過多
數據寶統計,截至8月25日收盤,滬深兩市共有59只個股連續5日或5日以上
河北遵化:精心準備迎開學
北京時間8月28日西甲聯賽第3輪,畢爾巴鄂競技主場對陣皇家貝蒂斯。畢爾
您好,現在漢格來為大家解答以上的問題。少年的繁體字圖片,少年的繁體
我是小前,我來為大家解答以上問題。diy小屋怎么自己制作房間,diy小屋
東方網記者包永婷8月27日報道:8月27日,上海大劇院迎來開業25周年。由
很多人對倒錯的歸結密室溺亡,倒錯的歸結不是很了解那具體是什么情況呢
C視覺攝影師周琦登臨龍泉山,猶如站在成都這座山水立體城市的觀景臺。
英國建議G7邀請中國參會,日本氣得直跳腳,六國獲中方同意入群,美國,中
大家好,今日關于【越吃越瘦的蔬菜7個讓人發胖的飲食習慣】迅速上了的
邯鄲小孩子好玩的地方有很多哦!首先,你可以去邯鄲的游樂園玩耍。那里
2023男籃世界杯如約而至,中國男籃于北京時間8月26日將打響小組賽的首