Skip to content

Vue 接入(@tripo3d/lens/vue) ​

在 Vue 里做埋点,最直接的方式是把坐标、事件、参数写成元素上的 data-trace* 字符串属性——核心的 行为埋点 · autoTrack 会在点击 / 曝光触发那一刻用 getAttribute 读取它们。这套属性是纯 DOM 契约,Vue 的原生 :(v-bind)绑定就能写入,响应式变量会随重渲染自动刷新到属性上,不需要任何适配器。

@tripo3d/lens/vue 是这套契约之上的可选 DX 层:把「逐属性绑定 + params 序列化 + 循环引用兜底 + 属性清理」打包成 v-trace 指令,并补上命令式逃生口(useTrace() / this.$trace)。本文先讲不装适配器的原生写法,再讲初始化,最后才是适配器带来的便利。

先看用法:原生绑定写 data-trace* ​

声明式采集只认 DOM 上的 data-trace* 字符串属性——点击 / 曝光触发时才用 getAttribute 读取,SDK 本身不理解、也不需要理解响应式。所以在 Vue 里你完全可以不装适配器,直接写属性:坐标固定就用静态 HTML 属性,需要动态就用原生 :(v-bind)绑定。

vue
<script setup lang="ts">
import { ref } from 'vue';
import { TraceEvent } from '@tripo3d/lens'; // 事件枚举:避免硬编码 'click' / 'expose'
const sku = ref('A1');
const tab = ref('docs');
</script>

<template>
  <!-- 1. 纯静态:坐标固定,直接写 HTML 属性 -->
  <button data-trace-key="home.banner.buy" data-trace-type="click">
    购买
  </button>

  <!-- 2. 动态 params + 枚举多事件:用 : 绑定,对象须自己 JSON.stringify -->
  <button
    data-trace-key="home.banner.buy"
    :data-trace-type="[TraceEvent.Click, TraceEvent.Expose].join(' ')"
    :data-trace-params="JSON.stringify({ sku })"
  >
    购买
  </button>

  <!-- 3. 坐标拼接:祖先 data-trace 段 + 叶子 data-trace-key,动态段用 : 绑定 → home.nav.docs -->
  <section data-trace="home">
    <a data-trace="nav" :data-trace-key="tab" data-trace-type="click">
      文档
    </a>
  </section>
</template>

为什么 : 绑定能拿到响应式

响应式的解析发生在 Vue 写入侧:每次组件渲染时 Vue 求值绑定表达式(ref 在此自动 unref 成快照),在 patch 阶段写进 DOM 属性;采集器在触发那一刻读属性,读到的始终是「已解析好且刚刷新过」的最新快照。整条链路无需 SDK 碰响应式。绑定值为 null / undefined 时 Vue 会自动移除该属性,无需手动清理。

要点(规则与手写 HTML 完全一致,详见 行为埋点 · 声明式埋点):

  • 锚点:元素必须带 data-trace 或 data-trace-key 才会被采集;单独写 data-trace-type / data-trace-params 不会触发。拼出的坐标须为合法 TracePath(2–8 段),否则静默丢弃。
  • 事件:data-trace-type 缺省为 click;多事件用空格分隔("click expose")。token 可从 @tripo3d/lens 引入 TraceEvent 常量避免硬编码——绑定场景写 :data-trace-type="TraceEvent.Click",多事件写 :data-trace-type="[TraceEvent.Click, TraceEvent.Expose].join(' ')"。但请注意:手写属性的值类型是 string,享受不到 v-trace 的 on 字段那样的类型约束(拼错不报错),想要类型安全请用 v-trace。
  • 参数:data-trace-params 是三者中唯一需要序列化的——: 绑定必须传字符串,直接绑对象会被写成 "[object Object]" 导致解析失败(见下方警告)。坐标(data-trace / data-trace-key)与事件(data-trace-type)都是字符串,直接写即可。

:data-trace-params 不要直接绑对象

:data-trace-params="{ sku }" 会被 Vue 的 setAttribute 转成字符串 "[object Object]"(DOM 属性只能存字符串,Vue 只做 toString、不做 JSON 序列化),采集端 JSON.parse 失败、参数丢失。必须写成 :data-trace-params="JSON.stringify({ sku })"。另外手写 JSON.stringify 遇到循环引用会直接抛错、可能中断渲染,需自行 try/catch——v-trace 已内置这层兜底。

属性写了不等于会上报

上面的写法只是把 data-trace* 落到了 DOM。真正的点击委托与曝光登记,需要一个已初始化、且开启 autoTrack 的核心实例——见下一节。

让埋点生效:初始化核心实例 ​

data-trace* 属性要被采集上报,前提是页面里已经 new TripoLens 并 init(),且装了 TrackingPlugin({ autoTrack: true })。这一步与「用不用适配器」无关,是所有方案的共同前提,只依赖核心包 @tripo3d/lens。

bash
pnpm add @tripo3d/lens
bash
npm install @tripo3d/lens
bash
yarn add @tripo3d/lens

new TripoLens() 出来就是个普通对象,与框架无关。用一个模块导出存起来,声明式采集即可全局生效,命令式 API 也随处可 import:

ts
// lib/trace.ts
import { TripoLens, TrackingPlugin } from '@tripo3d/lens';

// 尽早构造(快照入口 URL);autoTrack 必开,声明式采集才会启动
export const trace = new TripoLens({
  // event_format App 段
  app: 'shop',
  // 远端 CDN 配置 URL
  configUrl: 'https://cdn.example.com/lens/config.json',
  // 完整上报地址,由业务方给定
  endpoint: 'https://collect.example.com/report',
  plugins: [
    new TrackingPlugin({ autoTrack: true })
  ],
});

await trace.init();

在 main.ts 里 import 一次这个模块(或直接在入口构造),确保它在应用挂载前执行:

ts
// main.ts
import { createApp } from 'vue';
import App from './App.vue';
import './lib/trace'; // 触发构造 + init;纯声明式项目到这里就够了

createApp(App).mount('#app');

适配器不托管实例

与 Nuxt 适配器(模式 A 可自动创建客户端实例)不同,Vue 适配器只注册指令、不构造也不 init 实例。渠道归因要求实例在业务任何 URL 操作之前构造,所以你需自己尽早 new TripoLens(快照入口 URL)——放在 lib/trace.ts 顶层并尽早 import 即可。

构造实例的必填参数 ​

new TripoLens(params) 在构造期即校验 app / configUrl / endpoint 三项,缺任一直接抛错(无内置默认值);其余如 plugins、beforeEmit、onError、fetch 等均为可选,行为/错误/性能采集为 opt-in、需经 plugins 追加对应插件。各参数的类型、归一化与校验规则见 构造参数,初始化时序见 初始化。

埋点依赖 autoTrack

无论手写 data-trace* 还是用 v-trace,真正的点击委托与曝光登记都由 TrackingPlugin({ autoTrack: true }) 内的声明式采集器完成。不开 autoTrack,属性会照写但无人采集。

可选:Vue 适配器与声明式 v-trace ​

到这里,纯手写 data-trace* 已经能覆盖全部采集能力——响应式、SSR、曝光时序都不缺。适配器要解决的只是手写的重复与易错:逐属性绑定、params 的 JSON.stringify、循环引用兜底、属性清理。装上它,一句 v-trace 绑定即可替代多个属性;再加命令式逃生口(useTrace() / this.$trace),让声明式、命令式两种用法都更省心。

Vue 适配层已折入 core,作为 @tripo3d/lens 的子路径 @tripo3d/lens/vue 直接导出,无需单独安装适配器包。

core(@tripo3d/lens)把 vue(^3.3)声明为 optional peerDependency,请确保工程内已安装。在 main.ts 里以 app.use 注册适配器,并把上一节构造的实例传入:

ts
// main.ts
import { createApp } from 'vue';
import { TripoLensVue } from '@tripo3d/lens/vue';
import App from './App.vue';
import { trace } from './lib/trace'; // 上一节构造好的实例

createApp(App).use(TripoLensVue, { trace }).mount('#app');

用 v-trace 声明式埋点 ​

v-trace 的绑定值是 data-trace* 的对象化表达,支持响应式变量(变更后重渲染自动刷新属性)。绑定为字符串时按扁平 path 处理;为对象时显式指定字段:

vue
<script setup lang="ts">
import { ref } from 'vue';
import { TraceEvent } from '@tripo3d/lens/vue'; // 事件枚举一并 re-export
const sku = ref('A1');
const tab = ref('docs');
</script>

<template>
  <!-- 祖先段 v-trace="{ path: home }":叶子坐标自动前置 -->
  <section
    v-trace="{
      path: 'home'
    }"
  >
    <!-- 叶子 key + 单事件 → home.buy -->
    <button
      v-trace="{
        key: 'buy',
        on: 'click',
        params: { sku },
      }"
    >
      购买
    </button>

    <!-- 多事件(click + expose) -->
    <button
      v-trace="{
        key: 'card',
        on: [TraceEvent.Click, TraceEvent.Expose],
        params: { sku },
      }"
    >
      卡片
    </button>
  </section>

  <!-- 独立扁平 path(响应式插值) -->
  <a
    v-trace="{
      path: `home.nav.${tab}`,
      on: [TraceEvent.Click, TraceEvent.Expose],
    }"
  >
    文档
  </a>
</template>
绑定字段映射属性说明
keydata-trace-key叶子末段,与祖先链 data-trace 组合成完整坐标
pathdata-trace扁平坐标或祖先段
ondata-trace-type触发事件,缺省 click;可传数组多事件;用 TraceEvent 枚举或字符串字面量
paramsdata-trace-params上报参数,支持响应式;序列化失败(循环引用等)走插件 onError
exposePolicydata-trace-expose-policy元素级曝光去重策略,用 ExposePolicy 枚举取值(如 ExposePolicy.OncePerElement 列表项各报一次),免手拼字符串

坐标拼接、tripo 前缀、曝光去重等规则与手写 data-trace 一致,详见 行为埋点 · 声明式埋点。ExposePolicy 枚举与 TraceEvent 一样由 @tripo3d/lens/vue re-export(也可从 @tripo3d/lens 导入)。

手写 vs v-trace:该用哪种 ​

场景推荐
坐标固定、无动态参数直接写静态 data-trace*,最轻
有动态 params / 动态坐标段v-trace(自动 JSON.stringify + 循环引用兜底 + 多属性映射);或原生 : 绑定 + 手动 JSON.stringify
想要模板内联、不占用元素的 v-bind 通道v-trace

简言之:手写 data-trace*(含 : 绑定)在能力上等价于 v-trace,响应式、SSR、曝光时序都不缺;区别只在 DX——v-trace 把「逐属性绑定 + params 序列化 + 循环引用兜底 + 属性清理」打包掉,动态参数场景更省心、更不易错。

纯 HTML / 原生 JS 场景

不在 Vue 里(服务端模板、静态站、原生 JS)也能用同一套 data-trace*:直接写属性、用 setAttribute / dataset 动态更新即可,用法见 行为埋点 · 声明式埋点。

命令式埋点 ​

命令式 API(track / identify / captureException …)都挂在 TripoLens 实例上,所以分两步:先拿到实例,再调用。

拿到实例的两种方式 ​

按项目形态选其一。

路径一:自己管实例(最简,CSR 首选)

上一节的 lib/trace.ts 导出的实例与框架无关,哪儿都能 import——纯函数、组件、工具库都行:

ts
// 任意文件直接调用,不经过任何插件
import { trace } from '@/lib/trace';

// 上报标记为track类型
trace.track('pay.done', { orderId });
// 需要其他上报类型
trace.click('pay.button')
trace.expo('pay.button')

这条路完全不经过插件:既不用给 app.use 传 trace,声明式 v-trace 也照常工作(指令只写 data-trace* 属性、采集靠核心 autoTrack,本就不需要实例)。换句话说——手动初始化后实例就已经全局可用,用户自管即可。

路径二:交给插件注入(要逃生口 / DI / SSR 时)

把实例传给插件(即上一节的 app.use(TripoLensVue, { trace })),组件内改用框架风格的逃生口(useTrace() / this.$trace)拿:

ts
app.use(TripoLensVue, { trace }); // 传入后组件内 useTrace() / this.$trace 才可用

仅在以下情况才需要走这条路:

需求为什么要把实例传给插件
框架风格逃生口不想在组件里硬 import 模块变量,改用 useTrace() / this.$trace 从注入体系拿

Vue 的 app.use 与 React 的 <TraceProvider> 是同一件事

两者对等,都只做一件事——把实例放进框架的依赖注入体系,好让组件内的逃生口拿到。区别只在 API 形态:Vue 有 app.use(plugin, options) 全局插件机制,根注入一次即可;React 没有等价的全局机制,跨层级共享靠 Context,所以改用 <TraceProvider> 包裹应用根。详见 React 接入。

调用命令式 API ​

走路径二注入后,经逃生口拿到实例即可上报:

ts
// 组合式 API
import { useTrace } from '@tripo3d/lens/vue';
const trace = useTrace(); // 未安装插件或未传 trace 时抛错
trace.track('checkout.submit', { amount: 99 });
ts
// 选项式 API:this.$trace(未传 trace 时为 undefined,故判空调用)
this.$trace?.track('checkout.submit', { amount: 99 });

this.$trace 的类型已由适配器通过 declare module 'vue' 自动增广,无需在工程内手写声明。命令式方法的语义见 行为埋点 · 命令式埋点;曝光进阶 trackImpression / setExposurePolicy 同样挂在实例上,见 行为埋点 · 进阶。

SSR ​

指令实现了 getSSRProps,data-trace* 会随服务端 HTML 直出,hydration 后即可被采集,无需额外接线。服务端采集(性能 / 错误)机制见 SSR 采集;若用 Nuxt,优先用 Nuxt 适配器 自动接线。

插件选项 ​

app.use(TripoLensVue, options):

选项类型默认说明
traceTripoLens?—已构造(建议已 init)的实例;提供后才有 useTrace() / this.$trace
namestring?'trace'指令名,决定模板里写 v-<name>(默认即 v-trace)
onError(err) => void—params 序列化失败回调(坐标仍保留,仅丢 params)

除插件外,@tripo3d/lens/vue 还导出 TRACE_KEY(InjectionKey<TripoLens>,供不走 useTrace()、需要手动 inject 的场景)与 createTraceDirective(options?)(不经插件、手动 app.directive 注册指令的口子)。

故障排查 ​

症状原因处理
埋点不上报,控制台无报错没开 autoTrack,属性写了但无人采集构造时加 new TrackingPlugin({ autoTrack: true })
useTrace() 抛错未 app.use(TripoLensVue),或安装时未传 trace注册插件并传入实例
this.$trace 是 undefined安装时未传 trace在 app.use 的 options 里传 trace
点击有上报、曝光没有曝光阈值 / 去重策略见 曝光去重策略 与 AutoTrackOptions.exposeThreshold

下一步 ​

基于 MIT 协议发布(内部使用)