声明式埋点
- 预先声明埋点类型(提前封装好自定义的指令),在 DOM 或者组件上,通过设置即可以完成事件的统一上报;
- 声明式埋点是基于 vue 框架的自定义指令,可以一定程度的减小代码冗余解决代码耦合的问题。
- vue 中提供了自定义指令,在模版元素中插入自定义指令,可以跟踪元素的结构变化、跟踪数据变化,比 DOM 的 data 属性,从而更加方便抓取跟踪;
- 理论上,声明式埋点只需要关注两个问题:
- 需要埋点的 DOM 节点;
- 所需携带的数据;
- 声明式埋点标准写法:
// key表示埋点的唯一标识;act表示埋点方式 <button data-stat="{key:'111', act: 'click'}">埋点</button>
- 埋点触发及数据回传:
- 声明埋点后、遍历 DOM 树,找到 [data-stat] 节点,给这个 button 绑上 click 事件;
- 当事件被触发后,把参数 111 在回调函数中通过请求发出去。
声明式埋点优缺点
- 声明式埋点优点:
- 埋点和业务代码实现了解耦;
声明埋点是在 DOM 节点(html)上,而业务逻辑通常在 Javascript 文件中;
- 提高代码可维护和可阅读性;
- VUE 比较流行的埋点方式;
- 埋点和业务代码实现了解耦;
- 声明式埋点缺点:
- 需要手动在需要埋点的节点中添加指令。
声明式埋点需要解决的问题
- 遍历 DOM 树的时机
- 例如:一个表格的行数据是通过异步加载,而表格行中的操作按钮需要埋点,那么在 DOM ready 的时候去遍历,显然是无法找到的;
- 绑定埋点事件次数的问题
- 怎样保证埋点事件不会被重复绑定到元素上,一次操作发了N个埋点请求?
- 如何处理特有的埋点行为,
- 例如:页面展现埋点,区域展现埋点?
- 如何在解绑时,销毁已绑定的事件?
声明式埋点方案核心内容
- 通过声明式埋点来解耦业务代码
- 埋点方案需要兼容 Vue 应用和 jquery 应用(甚至所有应用)
- 需要支持页面展现埋点、区域展现埋点、点击埋点等多种埋点方式
- 极端情况下需要支持命令式埋点
钩子函数
-
按照官方文档,一个指令定义对象提供如下几个钩子函数:
- bind
- 只调用一次,指令第一次绑定到元素时调用,在这里可以进行一次性的初始化设置。
- inserted
- 被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
- update
- 所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。
- 指令的值可能发生了改变,也可能没有。
- 但是可以通过比较更新前后的值来忽略不必要的模板更新。
- 所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。
- componentUpdated
- 指令所在组件的 VNode 及其子 VNode 全部更新后调用。
- unbind
- 只调用一次,指令与元素解绑时调用。
- 其中 bind 和 update 是比较重要的两个钩子函数,
- 它能跟踪 DOM 的出现和变化,获取数据并数据上报埋点;
- bind
-
指令钩子函数会被传入以下参数:
- el
- 指令所绑定的元素,可以用来直接操作 DOM。
- binding
- 一个对象,包含指令的指令名、绑定值、表达式等。
- el
具体实现
- 页面曝光
- 对于 vue 的单页应用来说,页面的切换跟踪就是路由的变化;
- 但是在统一的路由钩子、放置每个页面不同的数据不太现实,于是就考虑在每个 view 页面根部埋下页面曝光数据,只要用户一访问该页面,就触发页面曝光;
- 坑位曝光
- 坑位的曝光实际就是一个 DOM 出现在用户视野范围内进行抓取;
- 需要借助全局滚动(scroll)事件,使用节流的方式检测目标坑位是否在可视范围内,在的话就触发坑位曝光
- 坑位点击
- 坑位的点击需要对目标坑位进行点击事件绑定;
- 在不影响目标坑位原有事件基础上,绑定点击的埋点上报,在元素unbind的时候解除对应点击事件
页面曝光(v-page-exposure)
- v-page-exposure
<div class="root" v-page-exposure="'a.b.c.d'"></div>
- a.b.c.d 分别为:
应用代码.页面代码.模块代码.坑位代码
,就是埋点统计需要的代码信息,把信息收集上报即可。- 需要注意的是指令信息是一个 js 表达式,如果不加引号会默认执行 js 变成一个对象取值报错。
- a.b.c.d 分别为:
坑位曝光(v-exposure)
- v-exposure
<div v-exposure="{gcms:[{type:1, uri:22},{type:2, uri:41}],seq:[1],spm:'a.b.c.d'}"></div> 复制代码
- 坑位曝光收集的是一个 js 对象,包含一些坑位的代码信息、位置信息、商品信息、跳转信息等。
- 坑位曝光采用实时上报,且曝光一次就不再曝光,
- 所以每次 bind 的时候、把所有曝光坑位收集在一个数组,坑位出现在用户可视范围内一次就上报弹出数组。
坑位点击(v-bury-click)
- v-bury-click
<div v-bury-click="JSON.stringify({gcms:[{type:1, uri:22},{type:2, uri:41}],spm:'1.0.0.0'})"></div> 复制代码
- 坑位点击也是一个 js 对象,包含坑位的各种信息,在页面加载的时候绑定点击事件,用户点击的时候上报埋点。
- 在实际使用过程中,埋点需要跟踪最新的数据信息,比如:
- 在加入购物车的环节中,加入购物车的按钮是同一个不变,但下一次选择商品的信息可能发生改变,所以每次点击按钮需要传递最新的埋点信息。
- 由于指令信息是一个 js 表达式,对象是一个引用类型,改变对象的值不会触发 update 钩子函数,所以需要 JSON 字符串化一下。