【Vue】利用 IntersectionObserver 实现自定义埋点曝光指令

visually.ts

export default (Vue) => {
  const options = {
    root: null, // 默认浏览器视窗
    threshold: 1 // 元素完全出现在浏览器视窗内才执行callback函数。
  }
  const timer = {} // 增加定时器对象
  // 当元素的移动趋势是出现在视窗内部时,元素全部在浏览器视窗内才会触发此 callback。
  // 此时 entry.isIntersecting 为 true
  // 当元素的移动趋势是离开视窗时,元素一触碰到视窗边界就会触发此 callback
  // 此时 entry.isIntersecting 为 false
  const callback = (entries, observer) => {
    entries.forEach(entry => {
      let visuallyData = null
      try {
        visuallyData = JSON.parse(entry.target.getAttribute('visually-data'))
      } catch (e) {
        visuallyData = null
        console.error('埋点数据格式异常', e)
      }
      // 没有埋点数据取消上报
      if (!visuallyData) {
        observer.unobserve(entry.target)
        return
      }
      // 必须出现在视窗内 5 秒以上,才会上报埋点信息
      if (entry.isIntersecting) {
        timer[visuallyData.id] = setTimeout(function () {
          // 上报埋点信息
          // sendUtm(visuallyData).then(res => {
          //   if (res.success) {
          //   // 上报成功后取消监听
          //     observer.unobserve(entry.target)
          //     visuallyList.push(visuallyData.id)
          //     timer[visuallyData.id] = null
          //   }
          // })
        }, 5000)
      } else {
        if (timer[visuallyData.id]) {
          clearTimeout(timer[visuallyData.id])
          timer[visuallyData.id] = null
        }
      }
    })
  }
  const observer = new IntersectionObserver(callback, options)

  const visuallyList = [] // 记录已经上报过的埋点信息

  const addListenner = (ele, binding) => {
    if (visuallyList.indexOf(binding.value) !== -1) return

    observer.observe(ele)
  }
  const removeListener = (ele) => {
    observer.unobserve(ele)
  }
  // 自定义曝光指令
  Vue.directive('visually', {
    bind: addListenner,
    unbind: removeListener
  })
}

注册

import visually from '@/directives/visually'
Vue.use(visually)

使用

<h1 
  v-visually 
  :visually-data="JSON.stringify({a:1,b:2})"
  style="border: 1px solid red;" 
>
  This is an about page
</h1>
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值