Vue手動埋點設(shè)計的方法實例
目標(biāo)
- 使用簡單;
- 減少代碼侵入性,不影響業(yè)務(wù)代碼閱讀
簡述
- 埋點一般是按頁面來管理的;
- 埋點的事件類型一般分為:點擊、曝光和頁面的進入和離開;
- 埋點的實質(zhì)就是在恰當(dāng)?shù)臅r機去發(fā)送請求,上送業(yè)務(wù)參數(shù)
按頁面管理埋點
在每個頁面目錄下創(chuàng)建events.js,管理當(dāng)前頁面的所有埋點事件。
為了減少埋點對業(yè)務(wù)代碼的影響,events.js中每個埋點的設(shè)置都是一個方法,可以在這個方法中處理數(shù)據(jù)得到埋點需要上送的數(shù)據(jù)。
該埋點設(shè)置的方法,返回一個埋點需要上送的參數(shù)的對象。
// src/views/PageA/events.js export default { // 按事件類型管理 CLICK: { back(ctx, data) { let { param1, param2 } = data; // ...處理傳入的數(shù)據(jù) return { eventValue: '返回', elementId: 'pageA-返回', // 需要上送的處理后的業(yè)務(wù)參數(shù) customData: { param1, param2 } }; } } }
遵循使用簡單的原則,調(diào)用埋點
// src/views/PageA/index.vue this.$track('CLICK.back', data);
實現(xiàn)上面的調(diào)用
- 使用
require.context()
聚合各個頁面目錄下的埋點設(shè)置(events.js
)。 - 聚合后的埋點設(shè)置按頁面作為模塊管理,使用頁面文件夾名稱作為模塊名。
- 結(jié)合路由管理,可以獲得當(dāng)前頁面的埋點配置模塊名。
- 在Vue.prototype下新增一個
$track()
方法。
// src/events/index.js import router from '@/router'; const ctx = require.context('@/views', true, /events\.js/); const configs = {}; ctx.keys().reduce((configs, path) => { if (/\.\/(\w+?)\/events\.js/.test(path)) { const moduleName = RegExp.$1; // 第一個子項 configs[moduleName] = resolveModule(moduleName, ctx(path)); } return configs; }, configs); function resolveModule(moduleName, module) { return Object.entries(module.default).reduce((all, [EVENT_TYPE, events]) => { all[EVENT_TYPE] = Object.keys(events).reduce((typeAll, key) => { typeAll[key] = buildTrackRequest( EVENT_TYPE.toLowerCase(), key, events[key] ); return typeAll; }, {}); }); } function buildTrackRequest(eventType, trackName, trackSetting) { return function trackRequest(...args) { // 看完后面再回過來看 if (typeof trackSetting !== 'function') { trackSetting = obj2fn(trackSetting); } // 執(zhí)行用戶定義的方法,返回埋點上送參數(shù) const [success, result] = invokeUserFn(trackSetting.bind(this, {})); if (!success) return result; // 傳入?yún)?shù),發(fā)送埋點請求 return tracker(result); } } export function track(eventPath, ...args) { let event = configs; let seg; const segs = eventPath.split('.'); // 2段式 沒有提供模塊名,則需要去路由配置上取 if (segs.length === 2) { const moduleName = router.currentRoute.meta?.eventModule; if (!moduleName) { throwError(`${eventPath} 沒有在路由配置中設(shè)置"meta.eventModule" 或者配置成3段式`); } event = event[moduleName]; } while ((seg = segs.shift())) event = event[seg]; if (!event) throwError(`${eventPath} 不存在`); // 給event綁定當(dāng)前調(diào)用環(huán)境 return event.call(this, ...args); } function throwError(err) { throw Error(`[Track Error] ${err}`); } export default function install(Vue) { Vue.prototype.$track = track; }
埋點設(shè)置支持對象形式
很多時候,可能不需要上送業(yè)務(wù)參數(shù),寫成一個對象更加簡單。
{ CLICK: { back: { eventValue: '返回', elementId: 'pageA-返回', } } }
有時候只需要上送簡單的業(yè)務(wù)字段,無需額外處理,也想使用對象的形式。
支持{{param1}}模板語法,同vue-template用法。(param1是埋點調(diào)用組件的屬性)
{ CLICK: { back: { eventValue: '返回', elementId: 'pageA-返回', customData: { param1: '{{param1}}' } } } }
將對象格式的埋點配置轉(zhuǎn)成方法形式的
const templateRE = /\{\{(.+?)\}\}/g; // 處理對象形式的埋點設(shè)置 function obj2fn(obj) { return function() { const that = this; // 處理模板字符串 (function resolveObj(obj) { Object.keys(obj).forEach(key => { const val = obj[key]; // 解析模板字符串 if (typeof val === 'string' && templateRE.test(val)) { obj[key] = val.replace(templateRE, (...match) => { // js嚴(yán)格模式下無法執(zhí)行with語法,以下是一種變通 return new Function(`with(this){return ${match[1]}}`).call(that); }); } // 遞歸處理 else if (isPlainObject(val)) resolve(val); }); })(obj); return obj; }; }
提供頁面級別的參數(shù)設(shè)置
很多時候一個頁面下的埋點都需要上送相同的參數(shù),如頁面名稱等。
提供beforeModuleEach和afterModuleEach兩個鉤子。
一般使用beforeModuleEach設(shè)置模塊(頁面)通用的埋點參數(shù),再合并單獨的埋點設(shè)置參數(shù),得到所有需要上送的參數(shù)。
function resolveModule(moduleName, module) { // 獲取`events.js`文件中設(shè)置的鉤子 const { beforeModuleEach, afterModuleEach } = module; // 獲取動態(tài)設(shè)置鉤子 const { beforeHooks, afterHooks } = getHooksByModule(moduleName); beforeModuleEach && beforeHooks.unshift(beforeModuleEach); afterModuleEach && afterHooks.unshift(afterModuleEach); return Object.entries(module.default).reduce((all, [EVENT_TYPE, events]) => { all[EVENT_TYPE] = Object.keys(events).reduce((typeAll, key) => { typeAll[key] = buildTrackRequest( EVENT_TYPE.toLowerCase(), key, events[key], beforeHooks, afterHooks ); return typeAll; }, {}); }); }
總結(jié)
到此這篇關(guān)于Vue手動埋點設(shè)計的文章就介紹到這了,更多相關(guān)Vue手動埋點設(shè)計內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vue設(shè)置提示和警告彈出框?qū)崙?zhàn)案例
頁面中會有很多時候需要彈窗提示,下面這篇文章主要給大家介紹了關(guān)于Vue設(shè)置提示和警告彈出框的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-02-02Vue-cli集成axios請求出現(xiàn)CORS跨域問題及解決
這篇文章主要介紹了Vue-cli集成axios請求出現(xiàn)CORS跨域問題及解決方案,具有很好的參考價值,希望對大家有所幫助,2023-10-10