日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
讓你監(jiān)聽(tīng)頁(yè)面所有點(diǎn)擊事件,你會(huì)怎么做?

前言

大家好,我是林三心,用最通俗易懂的話講最難的知識(shí)點(diǎn)是我的座右銘,基礎(chǔ)是進(jìn)階的前提是我的初心~

為玉溪等地區(qū)用戶提供了全套網(wǎng)頁(yè)設(shè)計(jì)制作服務(wù),及玉溪網(wǎng)站建設(shè)行業(yè)解決方案。主營(yíng)業(yè)務(wù)為成都網(wǎng)站設(shè)計(jì)、成都網(wǎng)站制作、玉溪網(wǎng)站設(shè)計(jì),以傳統(tǒng)方式定制建設(shè)網(wǎng)站,并提供域名空間備案等一條龍服務(wù),秉承以專業(yè)、用心的態(tài)度為用戶提供真誠(chéng)的服務(wù)。我們深信只要達(dá)到每一位用戶的要求,就會(huì)得到認(rèn)可,從而選擇與我們長(zhǎng)期合作。這樣,我們也可以走得更遠(yuǎn)!

背景

如果在做某個(gè)平臺(tái)的時(shí)候,我們需要統(tǒng)計(jì)用戶點(diǎn)擊的次數(shù),點(diǎn)擊的區(qū)域,點(diǎn)擊元素,等等,那我們應(yīng)該怎么去做比較合適呢?

舉個(gè)例子,我想在用戶點(diǎn)擊頁(yè)面上的每一個(gè)元素時(shí),我都能把這個(gè)元素的DOM節(jié)點(diǎn)信息記錄下來(lái),并且上報(bào)到服務(wù)器,便于后面產(chǎn)品那邊的統(tǒng)計(jì)用戶喜好~

公共函數(shù)?處處調(diào)用?

那我們要怎么去做呢?寫(xiě)一個(gè)公共函數(shù)嗎?然后去統(tǒng)一做上報(bào)嗎?

我首先寫(xiě)一個(gè)函數(shù),這是一個(gè)獲取點(diǎn)擊元素信息的函數(shù),我們可以在點(diǎn)擊的 event 參數(shù)中拿到目標(biāo)元素 target

圖片

const reportDOM = (e: PointerEvent) => {
  // 獲取到點(diǎn)擊的目標(biāo)元素
  const el = e.target
  // 把目標(biāo)元素解析成字符串
  const detail = htmlElementAsString(el)
  // 進(jìn)行上報(bào)
  report(detail)
}

// 上報(bào)函數(shù)
export const report = (detail) => {
  request(url, detail)
}
// 解析函數(shù)
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}`;
}

寫(xiě)完這幾個(gè)函數(shù)之后,我們只需要在每一個(gè)點(diǎn)擊事件中去插入這個(gè)函數(shù)即可

const click1 = (e: PointerEvent) => {
  reportDOM(e)
  
  // coding....
}
const click2 = (e: PointerEvent) => {
  reportDOM(e)
  
  // coding....
}
const click3 = (e: PointerEvent) => {
  reportDOM(e)
  
  // coding....
}

但是一個(gè)頁(yè)面中,點(diǎn)擊事件非常多啊,不可能每一個(gè)事件中去插入這個(gè)函數(shù),非常麻煩

全局監(jiān)聽(tīng) + elementFromPoint

基本做法

最好的辦法就是把 click 事件掛載在 window 身上,然后根據(jù) elementFromPoint 去計(jì)算坐標(biāo)匹配的元素,進(jìn)行解析上報(bào)

window.addEventListener(
  'click',
  (e: PointerEvent) => {
    // 通過(guò)坐標(biāo)計(jì)算出目標(biāo)元素
    const el = getTargetDomByPointerEvent(e);
    if (!el) return;
    // 把目標(biāo)元素解析成字符串
    const detail = htmlElementAsString(el);
    // 進(jìn)行上報(bào)
    report(detail);
  },
  true,
);

// 通過(guò)坐標(biāo)計(jì)算目標(biāo)元素
export const getTargetDomByPointerEvent = (e: PointerEvent) => {
  const el = document.elementFromPoint(e.pageX, e.pageY);
  if (el) {
    return el as HTMLElement;
  }

  return null;
};

拓展做法,只上報(bào)所需元素

我們可以通過(guò)配置一個(gè)數(shù)組 globalClickListeners ,只對(duì)我們所需要的 DOM 節(jié)點(diǎn)進(jìn)行監(jiān)聽(tīng)上報(bào),

const globalClickListeners = [
  {
    selector: '.cla', // 選擇器
  },
  {
    elementText: 'report2', // 元素文本
  },
  {
    selector: '.r', // 選擇器 + 元素文本
    elementText: 'report3',
  },
];

那么我們需要對(duì) window 的點(diǎn)擊監(jiān)聽(tīng)進(jìn)行改造

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);
          // 點(diǎn)擊元素是否包含所屬選擇器范圍
          const isIncludes = [...(els as unknown as any[])].includes(el);
          // 包含則上報(bào)
          if (isIncludes) {
            const detail = htmlElementAsString(el);
            // 進(jìn)行上報(bào)
            report(detail);
          }
        } else if (el.textContent === elementText) {
          // 文本相同情況
          const detail = htmlElementAsString(el);
          // 進(jìn)行上報(bào)
          report(detail);
        }
      });
    }
  },
  true,
);

小結(jié)

其實(shí)上面就是埋點(diǎn)庫(kù)中,全局點(diǎn)擊上報(bào)的一種解決方案,看似小問(wèn)題,但是其實(shí)面試了這么多人,感覺(jué)只有很少一部分人能回答的比較好~

結(jié)語(yǔ)

我是林三心

  • 一個(gè)待過(guò)小型toG型外包公司、大型外包公司、小公司、潛力型創(chuàng)業(yè)公司、大公司的作死型前端選手;
  • 一個(gè)偏前端的全干工程師;
  • 一個(gè)不正經(jīng)的掘金作者;
  • 逗比的B站up主;
  • 不帥的小紅書(shū)博主;
  • 喜歡打鐵的籃球菜鳥(niǎo);
  • 喜歡歷史的乏味少年;
  • 喜歡rap的五音不全弱雞

當(dāng)前文章:讓你監(jiān)聽(tīng)頁(yè)面所有點(diǎn)擊事件,你會(huì)怎么做?
網(wǎng)頁(yè)網(wǎng)址:http://www.5511xx.com/article/cdijeoc.html