js监控页面浏览时长和记录页面某一个图形浏览时长
需求:pm要求实现一个记录用户停留这个页面时长,后台记录,通过这些记录总结用户的习惯。比较坑的就是pm又提出了第二个需求,记录页面中某一个图表浏览时长。无语了,第一反应是不可能实现第二个需求。我们系统环境:vue,听到第一个需求的时候,脑子里有一个想法,应该不难实现,就是定时器的功能。第二个需求懵了,想象脑壳疼,挺麻烦的。聪明的我还是奋战几天实现了
·
需求:pm要求实现一个记录用户停留这个页面时长,后台记录,通过这些记录总结用户的习惯。比较坑的就是pm又提出了第二个需求,记录页面中某一个图表浏览时长。无语了,第一反应是不可能实现第二个需求。
我们系统环境:vue,听到第一个需求的时候,脑子里有一个想法,应该不难实现,就是定时器的功能。第二个需求懵了,想象脑壳疼,挺麻烦的。聪明的我还是奋战几天实现了?。
需求1 :记录页面浏览时长
思路:全局设置一个定时器和记录时间变量。路由导航后置钩子函数中,判断时间>0,向后台发送请求,并清空时间变量。
main.js文件
window.millisecond = 0
// 这个位置放置需要注意,初始化第一次进入页面时候,开启定时器。较少记录时间误差。
window.timer = setInterval(function () {
window.millisecond += 1
}, 1)
router.afterEach((route, to) => {
// 排除快速切换
if (window.millisecond !== 0) {
eventLog({ eventCode: 'GL-00002', remark: JSON.stringify({ route: to.path, browseTime: window.millisecond + 'ms' }) })
}
window.millisecond = 0
loadingBar.finish()
})
// 特别需要注意的一点,定时器及时清理。
clearInterval(window.timer)
需求2: 记录页面中某一个图形浏览时间
思路:这个功能代码在多个页面中都会使用,因此采用vue中混入(mixin),提高代码利用率。
技术难点1:定时器开启时间节点和关闭时间节点。
技术难点2: 如何定位图表在可视区域内。
技术难点3: 定时器利用和销毁。
技术难点4: 跳转页面前,如何处理图表记录时间。这次出现了两种情况,也头疼。
import { eventLog } from '@/common/request'
export default {
data() {
return {
timeArray: [], // 定时器id数组
scrollObj: {}, // 外层滚动视图
time: {}, // 定时器
browseTime: 0, // 可视区域浏览时间
targetDiv: {}, // 在可视区域图表元素
minBrowseTime: 5, // 最下停留时间,
routePath: '', // 路由地址
}
},
mounted() {
for (let i = 0; i < 1000; i++) {
if (i !== window.timer) {
clearInterval(i)
}
}
console.log(window.timer, this.time, '开始')
},
methods: {
/**
* @param {Array} targetDivArray 一个页面中需要记录图表数组
* { name: '图表名称', isShow: false, id: '图表id' }
* @param {String} routePath 路由地址
*/
browseTimeStart(targetDivArray, routePath) {
this.routePath = routePath
this.scrollObj = document.getElementsByClassName('page-loadmore-wrapper')[0]
this.scrollObj.removeEventListener('scroll', null, false)
this.browseTime = 0
clearInterval(this.time)
this.time = setInterval(() => {
this.browseTime += 1
}, 1000)
this.timeArray.push(this.time)
// 为了解决跳转到一个页面时候,如果不滚动一下,我们就无法开启定时器,不能精准记录停留时间
this.scrollObj.scrollTop = 1
this.scrollObj.addEventListener('scroll', () => {
// 为了解决,在A页面跳转到B页面,A页面没有销毁情况,在返回到A页面,
// this.scrollObjTop计算出现了偏差,所以又重新获取this.scrollObj对象
this.scrollObj = document.getElementsByClassName('page-loadmore-wrapper')[0]
for (let i = 0; i < targetDivArray.length; i++) {
let targetElement = document.getElementById(targetDivArray[i].id)
if (targetElement === null) {
targetDivArray[i].isShow = true
this.targetDiv = targetDivArray[i]
return
}
let height = targetElement.offsetHeight
let top = targetElement.getBoundingClientRect().top
let scrollObjTop = this.scrollObj.getBoundingClientRect().top
let screenHeight = Math.ceil(this.$store.state.wrapperHeight)
let upperLimit = screenHeight - height + scrollObjTop + 100
let lowerLimit = scrollObjTop - 80
// 难点在于这个公式总结,图表距离顶部高度>(外层滚动容器距离顶部高度 - 图表顶部80)
// 这个80可以动态调控,定义图表顶部不可见区域高度超80定义为不在可视化区域,发送后台请求,时间清空
// 图表距离顶部高度<(可视化区域高度 - 图表高度 + 外层滚动容器距离顶部高度 + 图表底部100)
// 这个100可以动态调控,定义图表底部不可见区域高度超100定义为不在可视化区域,发送后台请求,时间清空
if (lowerLimit < top && top < upperLimit) {
// console.log('+++++++++', targetDivArray[i].name)
this.targetDiv = targetDivArray[i]
if (!targetDivArray[i].isShow) {
targetDivArray[i].isShow = true
this.browseTime = 0
}
} else {
if (this.browseTime > this.minBrowseTime && targetDivArray[i].isShow) {
targetDivArray[i].isShow = false
eventLog({ eventCode: 'GL-00003-TIMER', remark: JSON.stringify({ route: this.$route.path, browseTime: this.browseTime + 's', name: targetDivArray[i].name }) })
// num = 0
this.browseTime = 0
this.targetDiv = {}
}
targetDivArray[i].isShow = false
}
}
}, false)
},
/**
* 加了keep-alive,跳转新页面,该页面不回走destroyed钩子函数,
* 需要我们在路由地址变化监听函数中手动调用这个方法
* 发送图表停留请求
*/
browseTimeEnd() {
if (Object.keys(this.targetDiv).length > 0 && this.browseTime > this.minBrowseTime) {
eventLog({ eventCode: 'GL-00003-TIMER', remark: JSON.stringify({ route: this.routePath, browseTime: this.browseTime + 's', name: this.targetDiv.name }) })
this.browseTime = 0
}
clearInterval(this.time)
this.timeArray.splice(0, 1)
}
},
/**
* 页面销毁时候,需要想后台发送有效的图表停留时长,并且销毁定时器,关闭滚动监控
*/
destroyed() {
if (typeof (this.scrollObj) !== 'undefined') {
this.browseTimeEnd()
this.scrollObj.removeEventListener('scroll', null, false)
}
},
}
更多推荐
已为社区贡献22条内容
所有评论(0)