国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發 > JS > 正文

js如何實現元素曝光上報

2024-05-06 16:54:05
字體:
來源:轉載
供稿:網友

進行數據上報的時候,經常會遇到列表數據曝光上報的問題,只對在當前可視范圍內的數據內容進行曝光上報,而對于未在可視范圍內的數據不進行曝光上報,等待用戶滾動頁面或者區域使元素出現在可視范圍內時才進行曝光上報。

解決方案

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

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

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) {  // 上報的邏輯}window.onscroll = function() {  nodes.forEach(node => {    if( isElementInViewport(node) ) {      report(node)    }  })  }

優點:兼容性好

缺點:

  • 需要關注頁面或者區域的scroll事件
  • 頻繁的scroll事件,性能問題

方案二:通過 IntersectionObserver 監聽元素是否處于可視范圍

function report(node) {  // 上報的邏輯}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)})

優點:

  • 無須關注 scroll
  • 回調是異步觸發,不會頻繁觸發,性能好

缺點:兼容性不好?

實際上,針對兼容性問題,w3c 官方提供了對應 polyfill, 因此intersectionObserver用于生產是可行的。

總結

筆者在實際運用中,通過 IntersectionObserver 封裝了一個簡單的調用庫,應用于可視化埋點 sdk 中,用于解決元素曝光問題,如下

require('intersection-observer'); // polyfillclass 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節點      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

調用方法:

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

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VeVb武林網。


注:相關教程知識閱讀請移步到JavaScript/Ajax教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 滦平县| 同仁县| 夹江县| 玉溪市| 汝州市| 闻喜县| 乐山市| 麻栗坡县| 青岛市| 满洲里市| 望谟县| 连山| 三江| 永州市| 东城区| 双辽市| 宁波市| 奉新县| 泽州县| 内江市| 内黄县| 华坪县| 北宁市| 皋兰县| 道孚县| 化隆| 宽甸| 犍为县| 团风县| 江门市| 五华县| 莲花县| 扶绥县| 烟台市| 敦化市| 锦屏县| 贡觉县| 韩城市| 正蓝旗| 霍邱县| 郁南县|