溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

js實(shí)現(xiàn)元素曝光上報(bào)的示例

發(fā)布時(shí)間:2021-02-03 11:47:42 來源:億速云 閱讀:173 作者:小新 欄目:web開發(fā)

小編給大家分享一下js實(shí)現(xiàn)元素曝光上報(bào)的示例,希望大家閱讀完這篇文章之后都有所收獲,下面讓我們一起去探討吧!

進(jìn)行數(shù)據(jù)上報(bào)的時(shí)候,經(jīng)常會(huì)遇到列表數(shù)據(jù)曝光上報(bào)的問題,只對(duì)在當(dāng)前可視范圍內(nèi)的數(shù)據(jù)內(nèi)容進(jìn)行曝光上報(bào),而對(duì)于未在可視范圍內(nèi)的數(shù)據(jù)不進(jìn)行曝光上報(bào),等待用戶滾動(dòng)頁面或者區(qū)域使元素出現(xiàn)在可視范圍內(nèi)時(shí)才進(jìn)行曝光上報(bào)。

解決方案

目前針對(duì)此類問題,主要有兩種解決方案。

方案一:監(jiān)聽頁面或者區(qū)域scroll事件,通過getBoundingClientRect接口取元素的位置與可視窗口進(jìn)行判斷。

function isElementInViewport(el) {
  var rect = el.getBoundingClientRect();

  var width_st = rect.width / 2,
    height_st = rect.height / 2;

  var innerHeight = window.innerHeight,
    innerWidth = window.innerWidth;


  if (  rect.top <=0 && rect.height > innerHeight 
    || rect.left <= 0 && rect.width > innerWidth
  ) {
    return rect.left * rect.right <= 0
      || rect.top * rect.bottom <= 0
  }

  return (
      rect.height > 0 
    && rect.width > 0 
    && ( ( rect.top >= 0 && rect.top <= innerHeight - height_st )
      || ( rect.bottom >= height_st && rect.bottom <= innerHeight ) )
    && ( ( rect.left >= 0 && rect.left <= innerWidth - width_st )
      || ( rect.right >= width_st && rect.right <= innerWidth ) )
  );
}

var nodes = document.querySelectorAll(".item")
function report(node) {
  // 上報(bào)的邏輯
}
window.onscroll = function() {
  nodes.forEach(node => {
    if( isElementInViewport(node) ) {
      report(node)
    }
  })
  
}

優(yōu)點(diǎn):兼容性好

缺點(diǎn):

  • 需要關(guān)注頁面或者區(qū)域的scroll事件

  • 頻繁的scroll事件,性能問題

方案二:通過 IntersectionObserver 監(jiān)聽元素是否處于可視范圍

function report(node) {
  // 上報(bào)的邏輯
}
var intersectionObserver = new IntersectionObserver(entries => {
  entries.forEach(entry => {
    if( entry.intersectionRatio > 0 ) {
      report(entry.target)
    }
  })
})
var nodes = document.querySelectorAll(".item")
nodes.forEach(node => {
  intersectionObserver.observe(node)
})

優(yōu)點(diǎn):

  • 無須關(guān)注 scroll

  • 回調(diào)是異步觸發(fā),不會(huì)頻繁觸發(fā),性能好

缺點(diǎn):兼容性不好?

實(shí)際上,針對(duì)兼容性問題,w3c 官方提供了對(duì)應(yīng) polyfill, 因此intersectionObserver用于生產(chǎn)是可行的。

總結(jié)

筆者在實(shí)際運(yùn)用中,通過 IntersectionObserver 封裝了一個(gè)簡單的調(diào)用庫,應(yīng)用于可視化埋點(diǎn) sdk 中,用于解決元素曝光問題,如下

require('intersection-observer'); // polyfill

class Exposure {
  constructor(callback) {
    if (!callback || typeof callback !== 'function') {
      throw new Error("need callback or selector param")
      return
    }
    this.intersectionObserver = new IntersectionObserver((entries) => {
      entries.forEach(item => {
        if (item.intersectionRatio > 0) {
          if (item.target) {
            callback(item.target, item)
            this.intersectionObserver.unobserve(item.target)
          }
        }
      })
    });
  }

  observe(selector, ignoreExposured) {
    if (!this.intersectionObserver || !selector) {
      return
    }
    let nodes = []
    if( this.isDOM(selector) ) { // dom節(jié)點(diǎn)
      nodes = [selector]
    }else { // 選擇器
      nodes = document.querySelectorAll(selector)
    }
    if (!nodes.length) {
      return
    }
    nodes.forEach(node => {
      if (!ignoreExposured && node.__wg__tracker__exposured__) {
        return
      }
      node.__wg__tracker__exposured__ = true
      // 開始觀察
      this.intersectionObserver.observe(
        node
      );
    })
  }

  disconnect() {
    if (!this.intersectionObserver) {
      return
    }
    this.intersectionObserver.disconnect()
  }

  isDOM(obj) {
    if( !obj ) {
      return false
    }
    if( typeof HTMLElement === 'object' ) {
      return obj instanceof HTMLElement
    }
    if( typeof obj === 'object' && obj.nodeType === 1 && typeof obj.nodeName === 'string' ) {
      return true
    }
    return false
  }
}

export default Exposure

調(diào)用方法:

function report() {}
var exposurer = new Exposure((node) => {
  report(node)
})
exposurer.observe(".item)

看完了這篇文章,相信你對(duì)“js實(shí)現(xiàn)元素曝光上報(bào)的示例”有了一定的了解,如果想了解更多相關(guān)知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道,感謝各位的閱讀!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

js
AI