基於Vue3實現一個前端埋點上報插件並打包發佈到npm

来源:https://www.cnblogs.com/zdsdididi/archive/2022/08/29/16634806.html
-Advertisement-
Play Games

前端埋點對於那些營銷活動的項目是必須的,它可以反應出用戶的喜好與習慣,從而讓項目的運營者們能夠調整策略優化流程提高用戶體驗從而獲取更多的$。這篇文章將實現一個Vue3版本的埋點上報插件,主要功能有 通過Vue自定義指令形式實現點擊事件上報 提供手動調用上報方法 上報每個頁面訪問人數與次數(UV,PV ...


前端埋點對於那些營銷活動的項目是必須的,它可以反應出用戶的喜好與習慣,從而讓項目的運營者們能夠調整策略優化流程提高用戶體驗從而獲取更多的$。這篇文章將實現一個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項目用來測試我們的本地包,它的創建方法這裡就不再詳細說了。最終它的目錄結構如下

image.png

插件開發

終端進入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多了個這樣的依賴

image.png

這樣就是表示play已經關聯到本地的包[email protected]的包了,然後我們在palymain.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函數被調用了,並且獲取到了傳來的額外參數.
image.png

點擊事件上報

點擊事件的上報我們提供兩種方式,一種是以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', (el, bind) => {
            el.addEventListener('click', () => {
                console.log(bind.value)
            })
        })

    }
}

我們在playpage1.vue種進行綁定指令測試

<template>
    <div v-click="{ eventName: 'test1' }">test1</div>
</template>

我們點擊test1便可以在控制台看到我們需要上報的數據

image.png

手動上報方法

我們可以手動調用上報方法掛載在實例全局即可,在vue3種掛載全局屬性的方法是app.config.globalProperties.xxx,所以我們定義一個全局上報方法$vtrack

export default {
    install: (app, options) => {
        app.directive('click', (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);
    };
  },
};

然後在項目中切換路由就會獲取到需要上報的事件

image.png

頁面停留時間(TP)

頁面停留時長同樣藉助effect函數,通過計算頁面變化的時間差從而上報頁面停留時長事件,一般當進入第二個頁面才會統計第一個頁面的TP,進入三個頁面計算第二個頁面的TP。。。所以我們把邏輯寫在getVisitor函數中然後給它改個名

//上報uv&pv&TP
const getVisitorAndTP = (app, prefix) => {
  const globalProperties = reactive(app.config.globalProperties);
  let startTime = new Date().getTime();
  let path = "";
  let lastPath = "";
  effect(() => {
    const endTime = new Date().getTime();
    const TP = endTime - startTime;
    startTime = endTime;
    lastPath = path;
    path = globalProperties.$route.path;
    //間隔為0不上報
    if (!TP) return;
    console.log({
      eventName: `${prefix}_${path}`,
    });
    //頁面停留時長小於0.5s不上報
    if (TP < 500) return;
    console.log({
      eventName: `${prefix}_${TP}_${lastPath}`,
    });
  });
};

export default {
  install: (app, options) => {
    getVisitorAndTP(app, "track");
    app.directive("click", (el, bind) => {
      el.addEventListener("click", () => {
        console.log(bind.value);
      });
    });
    //掛載全局用於手動上報
    app.config.globalProperties.$vtrack = (params) => {
      console.log(params);
    };
  },
};

上傳TP事件的格式為prefix_TP_path,因此我們切換頁面的時候可以看到同時上報的兩個事件

image.png

獲取公共參數

根據用戶傳來的固定參數baseParams和事件首碼prefix調整我們上報事件形式。假設在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,
    userAgent: "Chrome",
  },
  prefix: "app",
});
app.mount("#app");

然後修改一下我們的插件(這裡將uv/pv還有TP作為單獨參數上報,不再使用上面的eventName形式,太懶了,上面的寫法不想改了

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 為什麼要改變this指向? 我們知道bind,call,apply的作用都是用來改變this指向的,那為什麼要改變this指向呢?請看下麵的例子: var name="lucy"; let obj={ name:"martin", say:function () { console.log(this ...
  • JQuery篩選器方法 1.下一個元素 $("#id").next() $("#id").nextAll() $("#id").nextUntil("#i2") 2.上一個元素 $("#id").prev() $("#id").prevAll() $("#id").prevUntil("#i2") ...
  • 1. 提升用戶的開發體驗 開發體驗是衡量一個框架的指標之一 關於快速定位問題和列印警告信息和其他重要信息 Vue.js3 源碼中使用 initCustomFormatter 函數 該函數作用: 在開發環境下自定義formatter的 Chrome為例, 打開 DevTools 勾選 Console ...
  • 本文是深入淺出 ahooks 源碼系列文章的第十四篇,該系列已整理成文檔-地址。覺得還不錯,給個 star 支持一下哈,Thanks。 上一篇我們探討了 ahooks 對 DOM 類 Hooks 使用規範,以及源碼中是如何去做處理的。接下來我們就針對關於 DOM 的各個 Hook 封裝進行解讀。 u ...
  • 這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 最近幾天在學習three.js ,因為我相信只有實踐才能出真理,搗鼓搗鼓做了一個簡易的全景圖,這裡主要是分享做這個vue版全景圖中遇到的問題,有些代碼可能與其他做過全景圖的大佬有些相似畢竟原因都差不多 😀 本文屬於技術總結類的文章 將介 ...
  • 本文介紹如何基於 UNIAPP 使用 即時通訊SDK ZIM SDK 快速實現基本的消息收發功能。 1 uniapp im 即時通訊功能 方案介紹 即時通訊SDK ZIM SDK 提供瞭如下接入方案: 在此方案中,您需要通過您自己的業務系統實現以下業務邏輯: 搭建客戶端的用戶管理邏輯,並下發用戶 I ...
  • 單例模式 1 定義 保證一個類僅有一個實例,並提供一個訪問它的全局訪問點。 2 應用時機 當一個類的實例被頻繁使用,如果重覆創建這個實例,會無端消耗資源。比如 dialog 彈窗會被全局重覆使用 業務功能本身決定了全局只能有唯一的實例。比如 redux 管理的數據,只能有唯一的一份 3 應用場景 對 ...
  • 強制更新和創建低開銷的靜態組件 點擊打開視頻講解更加詳細 強制更新 如果你發現你自己需要在 Vue 中做一次強制更新,99.9% 的情況,是你在某個地方做錯了事。 你可能還沒有留意到數組或對象的變更檢測註意事項,或者你可能依賴了一個未被 Vue 的響應式系統追蹤的狀態。 然而,如果你已經做到了上述的 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...