vue聲明式埋點指令
背景
數(shù)據(jù)埋點是前端開發(fā)中的必經(jīng)一環(huán),可以用于統(tǒng)計頁面訪問量、按鈕點擊量、元素展示次數(shù)等。常見的是每個公司都會封裝一套自己的埋點sdk,在JS邏輯中調(diào)用對應(yīng)函數(shù)上報數(shù)據(jù)埋點。這種埋點的優(yōu)點是可以在元素多狀態(tài)的時候進行區(qū)分上報,缺點就是與業(yè)務(wù)邏輯耦合。
本文借助vue指令的實現(xiàn)了一套聲明式埋點方案,可以直接在template上進行指令埋點上報。為了適用不同公司,并且不對現(xiàn)有業(yè)務(wù)進行大的改動,將具體的埋點上報函數(shù)交由業(yè)務(wù)方實現(xiàn),將上報函數(shù)作為參數(shù)初始化指令。
實現(xiàn)
核心原理就是利用vue指令,指令的開發(fā)就不再描述了,需要的同學(xué)可以去vue官網(wǎng)看文檔。
常見的埋點可以分為三類:
頁面PV
一般是頁面初始化時進行上報,在指令初始化的時候上報即可,比較容易實現(xiàn)
點擊click
Vue 指令初始化時,會傳遞綁定指令的dom元素,所以我們可以通過對dom添加點擊事件進行監(jiān)聽來實現(xiàn)
元素曝光show
元素曝光實現(xiàn)稍微復(fù)雜些,需要借助
IntersectionObserver來判斷元素是否進入可視區(qū)域。
import "intersection-observer";
import { ITrackOptions } from "./types";
let ksLogShow: (arg0: any) => void;
const observer = new IntersectionObserver(
(entries) => {
entries.forEach(function (entry) {
if (entry.isIntersecting) {
let value: any = entry.target.getAttribute("kstrackParams");
const once = entry.target.getAttribute("once");
if (!value) {
return;
}
value = JSON.parse(value);
ksLogShow(value);
if (once === "true") {
observer.unobserve(entry.target);
}
}
});
},
{
threshold: [0.5],
}
);
export default {
install(Vue: any, options: ITrackOptions) {
const { logClick, logPV, logShow } = options;
ksLogShow = logShow;
Vue.directive("track", {
bind(el: any, binding: any) {
const { arg, value, modifiers } = binding;
if (arg === "click") {
el.addEventListener("click", () => {
logClick(value);
});
} else if (arg === "show") {
if (modifiers.once) {
el.setAttribute("once", modifiers.once.toString());
}
el.setAttribute("kstrackParams", JSON.stringify(value));
observer.observe(el);
} else if (arg === "pv") {
logPV(value);
}
},
});
},
};
使用方式
指令使用的參數(shù),與業(yè)務(wù)自己定義的logPV、logClick、logShow三個函數(shù)的參數(shù)是對應(yīng)的,參數(shù)的定義、實現(xiàn)、使用,全部由業(yè)務(wù)方自己決定。
初始化
import Vue from 'vue';
import logger from 'vue-logger-directive'
// 需要業(yè)務(wù)方提供三個函數(shù),分別用于PV統(tǒng)計、點擊統(tǒng)計、展示統(tǒng)計
import { logPV, logClick, logShow } from './logHandler';
Vue.use(logger, { logPV, logClick, logShow });
PV統(tǒng)計
export function logPV(params: {
page: string;
type: number;
}) {}
<div class="app"
v-logger:pv="{page: "app", type: 1}">
</div>
點擊統(tǒng)計
export async function logClick(params: {
page: string;
type: number;
action: string;
}) {
// 點擊統(tǒng)計邏輯
}
// 組件使用時
<div class="card" v-logger:click="{page: 'app', type: 1, action: 'join-btn'}"></div>
元素曝光
export async function logShow(params: {
page: string;
type: number;
action: string;
}) {
// 展示統(tǒng)計邏輯
}
// 組件使用時
<div class="card" v-logger:show="{page: 'app', type: 1, action: 'main-card'}"></div>
// 支持元素展示只執(zhí)行一次
<div class="card" v-logger:show.once="{page: 'app', type: 1, action: 'main-card'}"></div>
最后為了方便后續(xù)使用,發(fā)布到了npm中,有需要的可以自取
npm包地址:https://www.npmjs.com/package/vue-logger-directive
