ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

TimeMe.js源码剖析:“Start-Stop时间区间“数据结构如何优雅实现页面停留时长精准计时

TimeMe.js源码剖析:“Start-Stop时间区间“数据结构如何优雅实现页面停留时长精准计时 TimeMe.js源码剖析Start-Stop时间区间数据结构如何优雅实现页面停留时长精准计时【免费下载链接】TimeMe.jsA JavaScript library to accurately time how long a user views a web page, disregarding idle time and time when the tab or window is minimized.项目地址: https://gitcode.com/gh_mirrors/ti/TimeMe.jsTimeMe.js 是一个轻量级 JavaScript 计时库专注于页面停留时长精准计时它会自动剔除用户空闲时间以及浏览器最小化、切走标签页的时间只统计用户真正与页面交互的时长。整套库约 440 行代码其核心藏在timeme.js中一个叫startStopTimes的Start-Stop 时间区间数据结构里——本文带你拆解它的设计思路看看为什么记录开始/停止时间而不是累加计数器是打造可靠前端计时器的关键。为什么不用计数器直接累加直觉做法是每隔一秒执行一次totalTime 1。但页面停留时长统计有三个特殊要求用户离开或空闲时要能暂停——计数器只会一直涨无法回退要能随时查询当前总时长且不能累积误差页面、按钮、输入框等多个对象要并行计时。只要把用户活跃的时段记成一个个开始-停止时间区间需要时再求和以上问题全部迎刃而解。这就是 TimeMe.js 的设计出发点。数据结构一览startStopTimes 长什么样startStopTimes声明于timeme.js第 38 行startStopTimes: {}它实际是一个二级映射页面或元素名称 → 时间区间数组每个区间就是一对开始/停止时刻{ startTime: new Date(), stopTime: undefined }关键约定只有一条stopTime为undefined表示这段计时正在进行中。字段含义startTime该活跃段开始的时间点支持手动注入便于补录与测试stopTime undefined计时器运行中时长仍在累积stopTime为时间点该活跃段已结束时长被冻结startTimer 与 stopTimer防重复计时写进了设计里startTimertimeme.js第 82-101 行的逻辑很克制该名称没有记录时先创建区间数组若最后一个区间的stopTime还是undefined直接 return——上一个没结束之前不能开启新计时否则追加一个{ startTime, stopTime: undefined }新区间。stopTimer第 113-125 行则反向操作只有最后一个区间仍然开着才回填stopTime。这带来天然的幂等性无论 start/stop 被乱序、重复调用多少次时长都不会被重复统计。tests/tests.js里专门有两条用例验证这一点第 98-104 行、第 134-141 行连续调用两次startTimer第二次会被忽略连续两次stopTimer也不会出错。运行中也能精确到秒总时长是怎么算出来的getTimeOnPageInMillisecondstimeme.js第 144-167 行遍历该页面的所有区间求和已关闭区间stopTime - startTime仍在运行的开放区间临时以当前时间充当 stopTime第 158-160 行。这是整个设计中最巧妙的细节库里根本不维护一份运行中的累计值总时长永远从原始区间实时推导——任意时刻查询都是最新值且不存在反复加减带来的累积误差。自动剔除空闲与最小化事件驱动的开-关区间数据结构选对之后剔除干扰时间变得异常简单不是算完再扣掉而是不该记的时间压根不记。用户行为触发来源timeme.js库的反应切换标签页 / 最小化窗口visibilitychange含 moz/ms/webkit 前缀兼容探测第 307-319 行stopAllTimers()关闭所有开放区间回到页面同一事件或window.focus第 329-335 行startTimer()开启新区间长时间无操作mousemove / keyup / touchstart / scroll第 339-342 行 每 250ms 的checkIdleState轮询第 276-289 行累计空闲超过阈值 → 停止全部计时任何一次操作userActivityDetected第 209-214 行重置空闲倒计时打开demo/index.html可以直观体验空闲阈值设为 5 秒鼠标一停计时立刻冻结动一下鼠标计时恢复。多计时器并行页面与元素时长同时统计因为startStopTimes以任意字符串为键页面和页面内的元素自然可以共用同一套区间存储trackTimeOnElementtimeme.js第 49-68 行为指定元素挂上mouseover / mousemove / focus等监听把元素 ID 当作键来 start/stop 计时不同名称的区间互不干扰getTimeOnAllPagesInSeconds第 169-181 行一次输出全部页面的时长报告。对 SPA 应用只需stopTimer → setCurrentPageName → startTimer三步即可完成页面切换后的无缝续计用法见README.md的 API 章节。单元测试用固定时间点验证计时边界tests/tests.js的写法本身就值得借鉴——它利用startTimer / stopTimer允许注入时间点的能力把时间变成可控输入场景 2第 23-40 行注入固定时间点验证两个时间上重叠的页面各自统计正确5s 与 3s第 115-132 行验证手动注入的startTime只关联到它所属的那一个页面不会污染其他计时器。这也说明了可手动覆盖时间在生产中的价值既能精确测试也能与服务端时间对齐或补录历史数据。总结这套设计有哪些可借鉴之处用区间模型替代累加模型——总时长从原始区间实时推导天然支持暂停、恢复与并行多计时undefined即状态标记——stopTime undefined一个字段同时表达区间未闭合和计时中两种语义守卫写在入口——已在运行则直接 return让 API 幂等不依赖调用方保证顺序事件只负责开闭区间不负责算时长——可见性、空闲检测与时间计算彻底解耦职责清晰。如果你想为自己的网站加上真实交互时长统计通读这 400 多行的timeme.js压缩产物见timeme.min.js会是非常划算的一小时投入。【免费下载链接】TimeMe.jsA JavaScript library to accurately time how long a user views a web page, disregarding idle time and time when the tab or window is minimized.项目地址: https://gitcode.com/gh_mirrors/ti/TimeMe.js创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表