记一次前端时间埋点基于vue版本的

埋点(vue)

主要分为4个函数,pageIntevalpageTimelyRecordsetUrlModelFnrecordTrackId。主要依托于路由守卫。主要记录页面时长、最后一个页面的时候、页面的映射路径

pageInteval:主要是用于记录定时任务。说明,因为我们无法记录最后一个页面的时长,故采用将数据记录在localStorage里面,然后通过下一次进入页面的时候发起请求!具体代码如下:

let startTime = Date.now(); // 页面进入的开始时间
let currentTime = null; // 当前时间
let timer = null;
/*页面定时存储,主要记录最后一个页面*/
export const pageInteval = (to, from) => {
    // 当在登入页面
    if(from.path === '/login') {
        const firstAllInfo = JSON.parse(localStorage.getItem('XXX'));
        if(firstAllInfo) {
            axios....// 向后端发起请求
            localStorage.setItem('xxx', null);
            request.setTrackId('-1'); // 页面来源id重新从-1开始
        }
    }
    if(timer) {
        clearInterval(timer);
    }
    const recordStaticInfo = {
        pointUrl: to.path,// 因为是记录最后一个页面所以是to的路径
        pointType: 'page', // 为页面类型
        pointCustomization: JOSN.stringify(to.query) === '{}' : JSON.stringify(to.query)// 页面的附属参数
    }
	
	// 存储任务
	timer = setInterval(async () => {
        // 页面跳转后记录一下当前时间
        currentTime = currentTime - startTime;
        const allInfo = {
            ...recordInfo,
            pointSource: await request.getTrackId(),
            pageStayTime: Math.ceil(diff/1000);
        }
        localStorage.setItem('xxx', JSON.stringify(allInfo));
    }, 5000);
	// 初始化开始日期
	startTime = Date.now();
}

pageTimelyRecordpageInteval 函数类似,pageTimelyRecord 主要是路由路由跳转的时候获取from.path 的情况信息,这边就不再展开去讲了。

setUrlModelFn 主要是记录页面的映射路径,有朋友就要讲了,何为映射路径。那我就要说道说道了。其实也很简单,就是说,你当前页面在第四层级,那么我就要将前面三层的路径也要传给后端,就是 first->second->third->fouth具体代码实现如下。

function setUrlModelFn(direction) {
    // 补齐数组项,如果这边不补齐的化,后面对象查找就会报错, 因为我放的数据是存在路由meta的
    direction.meta.mapPaths = direction.meta.mapPaths || [];
    if(direction.meta.mapPaths.length < 4) {
        // 这里明确确定 这里只有4级菜单
        const sur = 4 - direction.meta.mapPaths.length;
        for(let i = 0; i < sur; i++) {
            // 用于补齐尾项
            direction.meta.mapPaths.push({id:'',name:'',pId: ''});
        }
    }
    const [
        {id: firstMenuId, pId: firstMenuPid},
        {id: secondMenuId, pId: secondMenuPid},
        {id: thirdMenuId, pId: thirdMenuPid},
        {id: fourMenuId, pId: fourMenuPid}
    ] = direction.meta.mapPaths
    // 这一步设置叶子节点菜单和当前叶子菜单的父级
    request.setUrlModel({
        urlLeafId: fourMenuId || thirdMenuId || secondMenuId || firstMenuId,
        urlParentId: fourMenuPid || thirdMenuPid || secondMenuPid || firstMenuPid
    })
}
// 传入to(下一个页面的相关信息,需要配合路由守卫去做)
setUrlModelFn(to);

在这里有一段关键的代码,就是寻找对应的映射路径,这里我单独拿出来,未来也许有需要。看如下代码。

// 获取映射路径
function recordMapPath(array, targetId) {
    const parentSubjectStock = [];// 存储父节点
    let going = true;// 是否已经找到要查找到的节点(false表示已找到不再继续)
    let findParentNode = function(array, id) {
        array.forEach((item) => {
            if(!going) {// 没有找到直接退出
                return
            }
            parentSubjectStock.push(item);
            if(item.id === id) {
                going = false
            } else if(item.children && item.children.length > 0) {
                findParentNode(item.children, id);
            } else {
                // 如果都没找到则剔除当前这一项,以免污染数据
                parentSubjectStock.pop();
            }
        })
        // 剔除一开始就找不到目标id的情况
        if(going) {
            parentSubjectStock.pop();
        }
    }
    findParentNode(array, targetId);
    // 返回自己想要的映射路径
    return parentSubjectStock.map((item) => ({
        id: item.id,
        name: item.name,
        pId: item.pId
    }))
}
/**
	@array 是有层级结构的菜单路径
	@id 对应的菜单叶子节点id
*/
recordMapPath(array, id)

上面这段代码就是说要找到此菜单所对应的菜单路径。

最后说下在路由守卫里面的情况吧,看如下代码和注释。

/*
	在路由前置守卫 beforeEach上面,配合页面跳转权限进行的判断
	
*/
// 如果当前角色在下一个页面有权限
const hasPermision = (role, route) => {
    let meta = route.meta;
    if(meta && meta.roles) return meta.roles.includes(role)
    return true
}
if(hasPermision(role, to)) {
    // 这里避免了在根路径和/login页面的时候发送接口请求
    if(from.path !== '/' && to.path !== '/login') {
        pageInteval(to, from);
    }
    // 这里避免在根路径和在重定向页面去发送接口请求
    if(from.path !== '/' && from.path !== 'redirect/index') {
        pageTimelyRecord(to, from);
    } else {
        next();
    }
}

最后,这边页面时长的埋点算是结束了!其实埋点这个部分非常的有广度,涉及的方方面面,包括页面错误埋点,按钮点击统计,页面跳转路径等等等多方面,未来有机会将会不断的补充和完善此部分的代码。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值