分享好友 前端技术首页 频道列表

基于Vue3实现前端埋点上报插件并打包发布到npm的详细过程

vue  2023-03-08 21:360

前端埋点对于那些营销活动的项目是必须的,它可以反应出用户的喜好与习惯,从而让项目的运营者们能够调整策略优化流程提高用户体验从而获取更多的$。这篇文章将实现一个Vue3版本的埋点上报插件,主要功能有

  • 通过Vue自定义指令形式实现点击事件上报
  • 提供手动调用上报方法
  • 上报每个页面访问人数与次数(UV,PV)
  • 上报用户在每个页面停留时长

项目环境搭建

本项目采用pnpm进行Monorepo环境搭建,因为未来这个项目可能会加入更多的工具包.

安装pnpm

npm install pnpm -g

初始化package.json

pnpm init

新建配置文件 .npmrc

shamefully-hoist = true

新建pnpm-workspace.yaml

packages:
  - "packages/**"
  - "play"

此时我们的packages目录和play目录便关联起来的,我们后面就可以愉快的在本地调试了。其中packages是我们各种包存放的地方,具体我们本次开发的埋点插件v-tracking便是其中之一。play则是一个Vue3项目用来测试我们的本地包,它的创建方法这里就不再详细说了。最终它的目录结构如下

基于Vue3实现前端埋点上报插件并打包发布到npm的详细过程

插件开发

终端进入v-tracking,执行pnpm init让它成为一个包,然后新建index.js作为入口。

在vue3是通过 app.use(plugin)的形式引入插件的,它会直接调用插件的install方法.install会接收到应用实例和传递给app.use()的额外选项作为参数。所以我们在v-tracking/index.js默认导出一个带有install函数的对象

export default {
    install: (app, options) => {
        console.log(options)
    }
}

进入paly执行pnpm add v-tracking此时你会发现paly下的package.json多了个这样的依赖

基于Vue3实现前端埋点上报插件并打包发布到npm的详细过程

这样就是表示play已经关联到本地的包v-tracking@1.0.0的包了,然后我们在palymain.js引入我们的插件

import { createApp } from 'vue'
import App from './App.vue'
import router from './router/index'
import vTracking from 'v-tracking'
const app = createApp(App)
app.use(router)
app.use(vTracking, {
    baseParams: {
        uid: 123
    }
})
app.mount('#app')

启动项目我们会发现install函数被调用了,并且获取到了传来的额外参数.

基于Vue3实现前端埋点上报插件并打包发布到npm的详细过程

点击事件上报

点击事件的上报我们提供两种方式,一种是以Vue自定义指令的形式,一种是手动调用上报方法。因为指令形式的点击上报并不能实现异步上报,所以加入手动调用上报的方法

vue自定义指令

首先我们简单了解一下什么是自定义指令。我们都用过Vue的内置的一系列指令 (比如v-modelv-show) 等,而Vue还提供了注册自定义指令的函数directive用法如下,其中el是我们绑定指令的dom,binding则是指令传来的一系列参数,比如

<div v-example:foo.bar="baz">

binding则是这样一个对象

{
  arg: 'foo',
  modifiers: { bar: true },
  value: /* `baz` 的值 */,
  oldValue: /* 上一次更新时 `baz` 的值 */
}

了解完指令我们便可以开始自定义指令click的开发了。其实很简单,就是监听el的点击事件然后获取到指令的value上报给后端即可

export default {
    install: (app, options) => {     
        app.directive('click', (el, bind) => {
            el.addEventListener('click', () => {
                console.log(bind.value)
            })
        })

    }
}

我们在playpage1.vue种进行绑定指令测试

<template>
    <div v-click="{ eventName: 'test1' }">test1</div>
</template>

我们点击test1便可以在控制台看到我们需要上报的数据

基于Vue3实现前端埋点上报插件并打包发布到npm的详细过程

手动上报方法

我们可以手动调用上报方法挂载在实例全局即可,在vue3种挂载全局属性的方法是app.config.globalProperties.xxx,所以我们定义一个全局上报方法$vtrack

export default {
    install: (app, options) => {
        app.directive('click', (el, bind) => {
            el.addEventListener('click', () => {
                console.log(bind.value)
            })
        })
        //挂载全局用于手动上报
        app.config.globalProperties.$vtrack = (params) => {
            console.log(params)
        }

    }
}

然后我们在page1.vue中进行使用

<template>
    <div v-click="{ eventName: 'test1' }">test1</div>
</template>

<script setup>
import { getCurrentInstance } from 'vue';
const { proxy } = getCurrentInstance()
proxy.$vtrack({ eventName: 'test1' })
</script>

同样的我们可以获取到我们需要的上报数据。

页面访问次数上报(pv,uv)

对于页面访问次数或者人数我们可以通过检测路由的变化从而上报当前页面事件。比如在page1页面我们可以以prefix_/page1(这个前缀可以由自己来定义)形式上报。但是在插件中如何检测路由变化呢?

起初我想通过监听onhashchange事件来监听路由变化的,但是经过测试发现Vue中的push事件根本不会触发onhashchange。所以我便引入了@vue/reactivity,通过它的reactive让传入app实例进行一个响应式包裹,再通过effect函数监听路由变化从而实现统计每个页面的进入事件,首先安装

pnpm add @vue/reactivity -w

然后引用

import { reactive,effect } from '@vue/reactivity'
//uv and pv
const getVisitor = (app, prefix) => {
  const globalProperties = reactive(app.config.globalProperties);
  effect(() => {
    const path = globalProperties.$route.path;
    console.log({
      eventName: `${prefix}_${path}`,
    });
  });
};

export default {
  install: (app, options) => {
    stayTime();
    getVisitor(app, "track");
    app.directive("click", (el, bind) => {
      el.addEventListener("click", () => {
        console.log(bind.value);
      });
    });
    //挂载全局用于手动上报
    app.config.globalProperties.$vtrack = (params) => {
      console.log(params);
    };
  },
};

然后在项目中切换路由就会获取到需要上报的事件

基于Vue3实现前端埋点上报插件并打包发布到npm的详细过程

页面停留时间(TP)

页面停留时长同样借助effect函数,通过计算页面变化的时间差从而上报页面停留时长事件,一般当进入第二个页面才会统计第一个页面的TP,进入三个页面计算第二个页面的TP。。。所以我们把逻辑写在getVisitor函数中然后给它改个名

//上报uv&pv&TP
const getVisitorAndTP = (app, prefix) => {
  const globalProperties = reactive(app.config.globalProperties);
  let startTime = new Date().getTime();
  let path = "";
  let lastPath = "";
  effect(() => {
    const endTime = new Date().getTime();
    const TP = endTime - startTime;
    startTime = endTime;
    lastPath = path;
    path = globalProperties.$route.path;
    //间隔为0不上报
    if (!TP) return;
    console.log({
      eventName: `${prefix}_${path}`,
    });
    //页面停留时长小于0.5s不上报
    if (TP < 500) return;
    console.log({
      eventName: `${prefix}_${TP}_${lastPath}`,
    });
  });
};

export default {
  install: (app, options) => {
    getVisitorAndTP(app, "track");
    app.directive("click", (el, bind) => {
      el.addEventListener("click", () => {
        console.log(bind.value);
      });
    });
    //挂载全局用于手动上报
    app.config.globalProperties.$vtrack = (params) => {
      console.log(params);
    };
  },
};

上传TP事件的格式为prefix_TP_path,因此我们切换页面的时候可以看到同时上报的两个事件

基于Vue3实现前端埋点上报插件并打包发布到npm的详细过程

获取公共参数

根据用户传来的固定参数baseParams和事件前缀prefix调整我们上报事件形式。假设在main.js用户传来这些数据

import { createApp } from "vue";
import App from "./App.vue";
import router from "./router/index";
import vTracking from "v-tracking";
const app = createApp(App);
app.use(router);
app.use(vTracking, {
  baseParams: {
    uid: 123,
    userAgent: "Chrome",
  },
  prefix: "app",
});
app.mount("#app");

然后修改一下我们的插件(这里将uv/pv还有TP作为单独参数上报,不再使用上面的eventName形式,太懒了,上面的写法不想改了

查看更多关于【vue】的文章

展开全文
相关推荐
反对 0
举报 0
评论 0
图文资讯
热门推荐
优选好物
更多热点专题
更多推荐文章
vue3+TS 自定义指令:长按触发绑定的函数
vue3+TS 自定义指令:长按触发绑定的函数而然间看到一个在vue2中写的长按触发事件的自定义指定,想着能不能把他copy到我的vue3项目中呢。编写自定义指令时遇到的几个难点1.自定义指令的类型在ts中写任何东西都要考虑到类型的问题,自定义指令的类型问题依然存

0评论2023-03-08326

基于ZR.VUE 前端的改造,页面刷新报错
 问题描述:前后端分离开发,分开部署. 页面刷新 直接报404 错误的解决办法提示:  先在 .env.development 中 配置 VUE_APP_BASE_API , 将 '/' 替换为 后端地址 'http://localhost:8888/'如果是对应的发布的正式环境,也要修改  .env.production 的VUE_APP_

0评论2023-03-08677

Vue3 企业级优雅实战 - 组件库框架 - 9 实现组件库 cli - 上
上文搭建了组件库 cli 的基础架子,实现了创建组件时的用户交互,但遗留了 cli/src/command/create-component.ts 中的 createNewComponent 函数,该函数要实现的功能就是上文开篇提到的 —— 创建一个组件的完整步骤。本文咱们就依次实现那些步骤。(友情提示

0评论2023-03-08947

vue-3 this概念
一、this概念官方是这样说的:在 setup()内部,this 不会是该活跃实例的引用因为 setup() 是在解析其它组件选项之前被调用的,所以 setup() 内部的 this 的行为与其它选项中的 this 完全不同这在和其它选项式 API 一起使用 setup() 时可能会导致混淆啥意思呢

0评论2023-03-08538

Vue3+TypeScript 项目中,配置 ESLint 和 Prettier
接上篇:从0搭建vite-vue3-ts项目框架:配置less+svg+pinia+vant+axios文档同步项目gitee:https://gitee.com/lixin_ajax/vue3-vite-ts-pinia-vant-less.git 一、Eslint:用于检测代码安装eslint相关依赖yarn add eslint eslint-plugin-vue @typescript-esli

0评论2023-03-08825

Vue中四种操作dom方法保姆级讲解 vue中如何操作dom
目录前言一、通过ref拿到dom的引用适用场景示例代码二、通过父容器的ref遍历拿到dom引用适用场景示例代码三、通过子组件emit传递ref适用场景示例代码四、通过:ref将dom引用放到数组中适用场景示例代码前言最近主管提出了许多优化用户体验的要求,其中很多涉及

0评论2023-03-08944

Vue状态管理工具Vuex工作原理解析 vuex五种状态
目录一、什么是vuex二、vuex的工作方式三、vuex的使用场景四、工作流程五、vuex的核心API六、应用七、vuex的工作流程一、什么是vuexVuex是vue项目的状态管理器(状态管理工具)。vue项目的状态是通过vue实例(组件)绑定的变量来体现。所以也可以说vuex是用来管理

0评论2023-03-08859

更多推荐