单文件番茄钟专注计时器:纯前端实现的开发记录

举报
yd_277098636 发表于 2026/10/22 07:48:16 2026/10/22
【摘要】 为什么做番茄钟专注工作法里番茄钟是最容易落地的:25 分钟专注 + 5 分钟休息,循环四次后长休息一次。市面上的番茄钟 App 大多要登录、要同步,反而把简单的事情复杂化。我的目标是做一个单文件、零依赖、离线可用的番茄钟网页:打开即用,数据只存在浏览器本地。 功能拆解核心功能只有四个:计时器:25/5/15 三档时长可切换,开始/暂停/重置任务清单:输入任务名,完成后勾选,清空已完成浏览器...

为什么做番茄钟

专注工作法里番茄钟是最容易落地的:25 分钟专注 + 5 分钟休息,循环四次后长休息一次。市面上的番茄钟 App 大多要登录、要同步,反而把简单的事情复杂化。我的目标是做一个单文件、零依赖、离线可用的番茄钟网页:打开即用,数据只存在浏览器本地。

功能拆解

核心功能只有四个:

  1. 计时器:25/5/15 三档时长可切换,开始/暂停/重置
  2. 任务清单:输入任务名,完成后勾选,清空已完成
  3. 浏览器通知:倒计时结束时弹出系统通知(即使标签页不在前台)
  4. 本地持久化:任务清单和累计专注番茄数存 localStorage,刷新不丢

非功能要求:单个 HTML 文件(含内联 CSS/JS),在手机和桌面浏览器都能正常显示。

计时器实现:为什么不用 setInterval 直接减

新手最容易写出的版本是 setInterval(() => seconds--, 1000),但它有两个坑:

  • 浏览器标签页切到后台后,setInterval 会被节流,计时变慢;
  • 系统休眠或卡顿会累积误差。

更稳的做法是记录目标结束时间戳:

let endAt = Date.now() + duration * 1000;
timer = setInterval(() => {
  const remain = Math.max(0, endAt - Date.now());
  render(remain);
  if (remain <= 0) { clearInterval(timer); onFinish(); }
}, 250);

轮询间隔取 250ms 而不是 1000ms,显示更平滑;实际剩余时间永远用时间戳差算,误差只来自单次回调延迟,不会累积。暂停时把当前剩余秒数存下来,恢复时重新算 endAt 即可。

通知权限:先请求再使用

浏览器通知需要用户授权,正确顺序是:页面加载时检查 Notification.permission,如果是 default 就在用户第一次点击"开始"时调用 Notification.requestPermission()——必须在用户手势里请求,否则 Chrome 会直接拒绝。倒计时结束时:

if (Notification.permission === "granted") {
  new Notification("番茄钟", { body: "25 分钟专注结束,休息一下吧!" });
}

再加一个页面标题闪烁作为兜底(用户拒绝通知权限时仍有提醒)。

任务清单与 localStorage

任务清单用数组存 {text, done},每次变更后 localStorage.setItem 全量写回。数据量小,全量序列化没有性能问题,反而避免了增量同步的状态错乱。页面加载时读回并渲染。累计完成的番茄数同样存一份,方便看长期趋势。

界面:一个大数字 + 三个按钮

番茄钟的界面越简单越好:屏幕中央一个大号倒计时,下方开始/暂停/重置,顶部三个时长切换 Tab,底部任务清单。配色用深色专注模式(深蓝背景 + 高对比数字),减少视觉干扰。全部用 flexbox 居中布局,媒体查询处理小屏幕。

发布与验证

最终成品是一个独立的 index.html,双击即可在浏览器打开;我还把它部署到了华为云 AI 开发者空间并通过 DevBridge 隧道生成公网预览地址,手机扫码就能用。完整代码随后会开源到 GitCode,敬请期待。

小结

这个项目的技术点都不难,但每个都踩过真实的坑:后台节流、通知权限时机、本地数据同步。把"能用"和"好用"之间的差距补上,靠的正是这些细节。下一个版本打算加白噪音和专注统计曲线,敬请期待。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。