前端埋点对于那些营销活动的项目是必须的,它可以反映出用户的喜好与习惯,从而让项目的运营者们能够调整策略优化流程提高用户体验从而获取更多的$。这篇文章将实现一个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项目用来测试我们的本地包,它的创建方法这里就不再详细说了。最终它的目录结构如下
插件开发
终端进入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
多了个这样的依赖
这样就是表示play
已经关联到本地的包v-tracking@1.0.0
的包了,然后我们在paly
的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 } }) app.mount('#app')
启动项目我们会发现
install
函数被调用了,并且获取到了传来的额外参数.
点击事件上报
点击事件的上报我们提供两种方式,一种是以Vue自定义指令的形式,一种是手动调用上报方法。因为指令形式的点击上报并不能实现异步上报,所以加入手动调用上报的方法
vue自定义指令
首先我们简单了解一下什么是自定义指令。我们都用过Vue的内置的一系列指令 (比如 v-model
或 v-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", { created: (el, bind) => { el.addEventListener("click", () => { console.log(bind.value); }); }, }); } }
我们在play
的page1.vue
进行绑定指令测试
<template> <div v-click="{ eventName: 'test1' }">test1</div> </template>
我们点击test1
便可以在控制台看到我们需要上报的数据
手动上报方法
我们可以手动调用上报方法挂载在实例全局即可,在vue3中挂载全局属性的方法是app.config.globalProperties.xxx
,所以我们定义一个全局上报方法$vtrack
export default { install: (app, options) => { app.directive("click", { created: (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); }; }, };
然后在项目中切换路由就会获取到需要上报的事件