Vue
封装DOM
元素曝光和点击埋点上报的自定义指令
一、前言
在项目中,免不了要上报一些曝光和点击埋点,如果在每处需要上报埋点的时候都写一套上报逻辑,代码就会很冗余,如果是vue项目的话,就可以通过自定义指令,将埋点上报逻辑全部封装在自定义指令里面,使用时,只需要上传数据即可完成埋点的上报。
二、实现曝光埋点上报
1. 定义曝光类
vue
并没有提供一个可以监听某个dom
元素是否曝光(即出现在可视区域)的方法,所以需要自己封装一个可以监听元素曝光的类,这里需要使用到一个API: IntersectionObserver API,它可以自动"观察"元素是否可见,如果不了解的话,可以看阅读这边文章,这里就不在赘述了。
// 声明 dom 元素曝光类
class DomExposure {
constructor(callback) {
// 如果传入的不是函数,抛出错误
if (!callback || typeof(callback) !== 'function') {
throw new Error("need callback or selector param")
}
// IntersectionObserver 为浏览器原生提供的构造函数
this.intersectionObserver = new IntersectionObserver((entries) => {
entries.forEach(item => {
// intersectionRatio 为目标元素的可见比例,大于 0 代表可见
if (item.intersectionRatio > 0) {
if (item.target) {
callback()
// 曝光一次后停止监听,看需求
// this.unobserve(item.target)
}
}
})
})
}
// 停止观察
unobserve(exposureHTMLElement) {
this.intersectionObserver.unobserve(exposureHTMLElement)
}
// 开始观察
observe(exposureHTMLElement) {
this.intersectionObserver.observe(exposureHTMLElement);
}
// 关闭观察器
disconnect() {
if (!this.intersectionObserver) {
return
}
this.intersectionObserver.disconnect()
}
}
2. 声明曝光埋点上报函数
// 观察 dom 元素曝光,并完成曝光埋点上报
function bindExposureObserver(el, reportData) {
const exposure = new DomExposure(() => {
// 曝光埋点上报
// 封装好的埋点上报方法
reportMethod(reportData)
})
// 观察当前dom元素
exposure.observe(el)
}
该函数实例化了一个DomExposure
类,传入曝光后的回调,当观察到dom
元素曝光时,就执行回调,完成埋点的上报。
3. 声明点击埋点上报函数
// 给 dom 元素绑定点击事件,完成点击埋点上报
function bindClick(el, reportData) {
el.addEventListener('click', () => {
// 点击埋点上报
// 封装好的埋点上报方法
reportMethod(reportData)
}, 'false')
}
该函数给dom
元素绑定了点击事件,当点击事件触发时,自动完成点击埋点的上报
4. 注册 v-report
自定义指令
const report = {
inserted(el, binding) {
const expReportData = binding.value.expReportData
const clickReportData = binding.value.clickReportData
// 如果存在expReportData,代表需要上报曝光埋点
if(expReportData) {
bindExposureObserver(el, expReportData)
}
// 如果存在clickReportData,代表需要上报点击埋点
if(clickReportData) {
bindClick(el, clickReportData)
}
}
}
// 注册 report 指令
Vue.directive('report', report)
5. 自定义指令的使用
Vue.component('my-button', {
data() {
return {
pageId: 1,
pageName: '我的页面'
}
},
computed: {
reportData() {
const commonData = {
page_id: this.pageId,
page_name: this.pageName
}
return {
expReportData: {
...commonData,
test: '曝光了'
},
clickReportData: {
...commonData,
test: '点击了'
}
}
}
},
template: `<div v-report="reportData">
<p>点击完成埋点上报</p>
</div>`
})
只要在需要的地方添加v-report
指令,并传入规定好的数据格式,即可完成埋点的上报。