您好,登錄后才能下訂單哦!
本篇文章為大家展示了怎么在vue項目中實現(xiàn)前端埋點,內(nèi)容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。
Vue具體輕量級框架、簡單易學、雙向數(shù)據(jù)綁定、組件化、數(shù)據(jù)和結(jié)構(gòu)的分離、虛擬DOM、運行速度快等優(yōu)勢,Vue中頁面使用的是局部刷新,不用每次跳轉(zhuǎn)頁面都要請求所有數(shù)據(jù)和dom,可以大大提升訪問速度和用戶體驗。
埋點方案的確定。業(yè)界的埋點方案主要分為以下三類:
代碼埋點:在需要埋點的節(jié)點調(diào)用接口,攜帶數(shù)據(jù)上傳。如百度統(tǒng)計等;
可視化埋點:使用可視化工具進行配置化的埋點,即所謂的「無痕埋點」,前端在頁面加載時,可以讀取配置數(shù)據(jù),自動調(diào)用接口進行埋點。如開源的Mixpanel;
無埋點:前端自動采集全部事件并上報埋點數(shù)據(jù)。如國內(nèi)的神策數(shù)據(jù)等;
在當時排期緊湊,人力緊缺的情況下,顯然不允許我們?nèi)ラ_發(fā)可視化埋點方案和無埋點方案,所以只能采取代碼埋點方案。
命令式埋點
命令式埋點,顧名思義,開發(fā)者需要手動在需要埋點的節(jié)點處進行埋點。如點擊按鈕或鏈接后的回調(diào)函數(shù)、頁面ready時進行請求的發(fā)送。大家肯定都很熟悉這樣的代碼:
// 頁面加載時發(fā)送埋點請求 $(document).ready(function(){ // ... 這里存在一些業(yè)務(wù)邏輯 sendRequest(params); }); // 按鈕點擊時發(fā)送埋點請求 $('button').click(function(){ // ... 這里存在一些業(yè)務(wù)邏輯 sendRequest(params); });
可以很容易發(fā)現(xiàn),這樣的做法很有可能會將埋點代碼侵入業(yè)務(wù)代碼,這使整體業(yè)務(wù)代碼變得繁瑣,容易出錯,且后續(xù)代碼會愈加膨脹,難以維護。所以,我們需要讓埋點的代碼與具體的業(yè)務(wù)邏輯解耦,即 聲明式埋點 ,從而提高埋點的效率和代碼的可維護性。
聲明式埋點
理論上,聲明式埋點只需要關(guān)注兩個問題:
需要埋點的DOM節(jié)點;
所需攜帶的數(shù)據(jù)
因此,可以很快想出一個聲明式埋點的方法:
// key表示埋點的唯一標識;act表示埋點方式 <button data-stat="{key:'111', act: 'click'}">埋點</button>
那么可以去遍歷DOM樹,找到 [data-stat] 的節(jié)點,給這個button綁上click事件,把這些參數(shù)在回調(diào)函數(shù)中通過請求發(fā)出去。
在DOM節(jié)點(html)上聲明埋點,與業(yè)務(wù)邏輯(通常在Javascript文件中)就解耦了。調(diào)用也很方便。
看起來很美,但這樣就能解決問題了嗎?顯然是不夠的。還需要解決以下問題:
遍歷DOM樹的時機問題,一個簡單的例子,一個表格的行數(shù)據(jù)是通過異步加載,而表格行中的操作按鈕需要埋點,那么在DOM ready的時候去遍歷,顯然是無法找到的
綁定埋點事件次數(shù)的問題,怎樣保證埋點事件不會被重復(fù)綁定到元素上,一次操作發(fā)了N個埋點請求?
如何處理特有的埋點行為,如頁面展現(xiàn)埋點,區(qū)域展現(xiàn)埋點?
如何在解綁時,銷毀已綁定的事件?
1.自定義指令實現(xiàn)埋點數(shù)據(jù)統(tǒng)計
在項目中通常需要做數(shù)據(jù)埋點,這個時候,使用自定義指令將會變非常簡單
在項目入口文件 main.js 中配置我們的自定義指令
// 坑位埋點指令 Vue.directive('stat', { bind(el, binding) { el.addEventListener('click', () => { const data = binding.value; let prefix = 'store'; if (OS.isAndroid || OS.isPhone) { prefix = 'mall'; } analytics.request({ ty: `${prefix}_${data.type}`, dc: data.desc || '' }, 'n'); }, false); } });
2.使用路由攔截統(tǒng)計頁面級別的 PV
由于第一次在單頁應(yīng)用中嘗試數(shù)據(jù)埋點,在項目上線一個星期之后,數(shù)據(jù)統(tǒng)計后臺發(fā)現(xiàn),首頁的 PV 遠遠高于其它頁面,數(shù)據(jù)很不正常。后來跟數(shù)據(jù)后臺的人溝通詢問他們的埋點統(tǒng)計原理之后,才發(fā)現(xiàn)其中的問題所在。
傳統(tǒng)應(yīng)用,一般都在頁面加載的時候,會有一個異步的 js 加載,就像百度的統(tǒng)計代碼類似,所以我們每個頁面的加載的時候,都會統(tǒng)計到數(shù)據(jù);然而在單頁應(yīng)用,頁面加載初始化只有一次,所以其它頁面的統(tǒng)計數(shù)據(jù)需要我們自己手動上報
解決方案
使用 vue-router 的 beforeEach 或者 afterEach 鉤子上報數(shù)據(jù),具體使用哪個最好是根據(jù)業(yè)務(wù)邏輯來選擇。
const analyticsRequest = (to, from) => { // 只統(tǒng)計頁面跳轉(zhuǎn)數(shù)據(jù),不統(tǒng)計當前頁 query 不同的數(shù)據(jù) // 所以這里只使用了 path, 如果需要統(tǒng)計 query 的,可以使用 to.fullPath if (to.path !== from.path) { analytics.request({ url: `${location.protocol}//${location.host}${to.path}` }); } }; router.beforeEach((to, from, next) => { if (to.matched.some(record => record.meta.requiresAuth)) { // 這里做登錄等前置邏輯判斷 // 判斷通過之后,再上報數(shù)據(jù) ... analyticsRequest(to, from); } else { // 不需要判斷的,直接上報數(shù)據(jù) analyticsRequest(to, from); next(); } });
在組件中使用我們的自定義指令
基于 jquery + widget 的老項目,
那么在這些項目中的DOM操作是jquery甚至原生DOM API來實現(xiàn),Vue的自定義指令就無法工作
基于MutationObserver API的Mixin
MutationObserver是在DOM3標準中提出的標準API,提供讓開發(fā)者感知到在某一個DOM節(jié)點變更的能力。可以監(jiān)聽以下場景:
childList: 目標節(jié)點的子節(jié)點插入刪除引起的變更
attributes: 目標節(jié)點屬性改變引起的變更
characterData: 目標節(jié)點的文本節(jié)點改變引起的變更,如通過appendData()等
subtree: 目標節(jié)點的子孫節(jié)點改變引起的變更
attributeOldValue:當attribute監(jiān)聽被設(shè)定為true時,可以記錄改變前的屬性值
characterDataOldValue:當characterData監(jiān)聽被設(shè)定為true時,可以記錄改變前的屬性值
attributeFilter:可以設(shè)定需要監(jiān)聽的屬性列表
但為了保證MutationObserver可以在所有瀏覽器上正常工作,我們?nèi)匀灰肓诉@個API的polyfill,詳情可見這里。
在此能力的前提下,我們就可以在任意的DOM操作下觸發(fā)Vue進行重新解析指令。
我們將 MutationObserver 封裝進一個 Vue mixin , 非Vue應(yīng)用的業(yè)務(wù)代碼只需要引入這個mixin,這樣也可以很好地解耦。
詳細的實現(xiàn)原理可以見以下偽代碼:
let observer; export default { ready() { // 開啟監(jiān)聽 observer = new MutationObserver(mutations => { this.$compile(this.$el); }); observer.observe(this.$el, config); }, destroyed() { // 清理工作 observer.disconnect(); observer.takeRecords(); } }
上述內(nèi)容就是怎么在vue項目中實現(xiàn)前端埋點,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關(guān)注億速云行業(yè)資訊頻道。
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。