watchEffect 可自动收集依赖实现阅读进度埋点:滚动时计算可见占比,达25%/50%/75%/100%阈值且未上报则触发轻量异步上报,并支持IntersectionObserver增强段落级精度。

watchEffect 是 Vue 3 中响应式副作用的“自动依赖收集”工具,非常适合监听滚动位置、可视区域变化等动态状态。实现长文本阅读进度自动埋点,核心思路是:**在用户滚动时,实时计算当前可见内容占比,当达到预设阈值(如 25%、50%、75%、100%)且未上报过时,触发一次埋点上报**。
监听滚动并计算阅读进度
把文本容器设为可滚动元素(如 <div ref="contentRef" class="text-container">),用 watchEffect 监听其 scrollTop、clientHeight 和 scrollHeight 的变化:
- 阅读进度 =
(scrollTop + clientHeight) / scrollHeight(即“已看到的底部位置”占全文高度的比例) - 需确保 DOM 已挂载,所以通常在
onMounted后才开始 watch;也可配合nextTick确保元素尺寸就绪 - 注意防抖——避免高频滚动触发大量计算,可在内部用
setTimeout节流,或使用lodash.throttle
用 ref 记录已上报的进度节点
定义一个响应式 ref(如 const reported = ref(new Set())),用于记录哪些整数百分比(如 25、50、75、100)已上报过:
- 每次算出进度
ratio后,四舍五入到最近的 25% 区间:const level = Math.round(ratio * 4) * 25 - 只对
level ∈ [25, 50, 75, 100]且!reported.value.has(level)的情况执行上报 - 上报后立即
reported.value.add(level),避免重复
结合 IntersectionObserver 做更精准的“段落级”埋点(可选增强)
单纯靠滚动比例可能不够精细(比如快速滑动跳过中间段)。可额外为每个语义化段落(<p> 或 <section>)绑定 IntersectionObserver,再用 watchEffect 统一协调:
立即学习“前端免费学习笔记(深入)”;
- 每个段落 ref 收集后,用
new IntersectionObserver监听其isIntersecting和intersectionRatio - 将各段落的可见状态存入一个
ref数组(如visibleSections),watchEffect依赖它 - 在 effect 内聚合统计:比如“前 N 段中 ≥50% 可见的段落数 / 总段数”,作为更语义化的阅读深度指标
上报逻辑要轻量、异步、带上下文
埋点请求本身不应阻塞 UI,建议封装成无等待的 sendTrackEvent 函数:
- 携带必要字段:文章 ID、用户 ID、设备类型、当前进度 level、时间戳、URL
- 使用
fetch(..., { keepalive: true })或navigator.sendBeacon,确保页面卸载前也能发出 - 避免在 watchEffect 中直接 await 请求——应改为 fire-and-forget 方式,例如
void track('read_progress', { level })


















