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

首頁 > 語言 > JavaScript > 正文

js如何實現元素曝光上報

2024-05-06 15:36:07
字體:
來源:轉載
供稿:網友

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

解決方案

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

方案一:監聽頁面或者區域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            
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

主站蜘蛛池模板: 大安市| 边坝县| 沾化县| 慈溪市| 宜春市| 鞍山市| 和田市| 酒泉市| 正定县| 华容县| 南投市| 武城县| 土默特左旗| 当雄县| 保德县| 临清市| 泰和县| 扬州市| 五河县| 闸北区| 潜江市| 淅川县| 霍邱县| 昌图县| 彰化县| 清苑县| 三门县| 新乐市| 石首市| 绥中县| 社旗县| 礼泉县| 织金县| 怀仁县| 监利县| 万载县| 玉屏| 临沧市| 竹北市| 临泽县| 岳阳市|