用实现轻量离线体重趋势图:数据存localstorage并校验格式,横轴等距分配天数,纵轴动态计算范围,手动绘制坐标与标签,输入框限制范围与精度,日期统一用iso字符串和tolocaledatestring安全格式化。

用 <canvas></canvas> 画体重趋势折线图,别碰 SVG 或第三方库
纯 HTML 页面做体重记录,核心诉求是“轻量、离线可用、改数据就刷新图表”,<canvas></canvas> 是最直接的选择。SVG 虽然语义清晰,但动态重绘坐标轴和标签要写一堆 DOM 操作;引入 Chart.js 等库反而让单页变重,还依赖网络或本地打包。
关键点在于:数据存进数组,用 ctx.lineTo() 连点,用 ctx.fillText() 手动标日期和数值——不靠自动适配,自己算像素位置,反而可控。
- 横轴按天数等距分配,不硬套真实日期(避免时间戳换算出错)
- 纵轴范围取
Math.min()和Math.max()加上下 0.5kg 缓冲,防止文字贴边 - 体重值建议统一用
Number类型,避免字符串 “72.5” 导致排序/计算异常
localStorage 存体重数据,但必须校验格式再读取
页面刷新不丢数据,靠 localStorage 最省事。但用户可能手动改过 localStorage 里的值,或旧数据结构变了,直接 JSON.parse() 容易报错卡死图表。
实操时加一层防御:
- 用
try...catch包住JSON.parse(localStorage.getItem('weightLog')) - 解析后检查是否为数组,且每项含
date(ISO 格式字符串)和value(数字) - 不符合就用默认空数组,不中断后续渲染
示例校验逻辑:
const raw = localStorage.getItem('weightLog');
let data = [];
try {
const parsed = JSON.parse(raw);
if (Array.isArray(parsed) && parsed.every(d => d.date && typeof d.value === 'number')) {
data = parsed;
}
} catch (e) { /* 忽略错误 */ }
输入框限制体重值范围与精度,防乱输
用户手抖输个 “800” 或 “72.3456” 很常见,前端不做拦截,后端没得拦(这是纯静态页),数据就歪了。
- 用
<input type="number" min="40" max="150" step="0.1">,浏览器原生限制基础范围 - 提交前再用正则
/^\d{2,3}(\.\d{1,1})?$/强制最多一位小数(避免 72.30 显示成 72.3) - 输入后立刻
parseFloat(value).toFixed(1)标准化,再存入数组
注意:step="0.1" 在部分 Safari 版本下失效,所以 JS 校验不能省。
日期显示用 toLocaleDateString(),别拼接字符串
记录体重总得带日期,但用户系统区域不同,有的显示 “2024/5/20”,有的是 “20.05.2024”。硬写 date.getFullYear() + '-' + (date.getMonth()+1) 会漏掉补零、时区、本地习惯。
- 一律用
new Date(dateString).toLocaleDateString(navigator.language, { year: 'numeric', month: 'short', day: 'numeric' }) - 如果存的是时间戳,先
new Date(timestamp)再调用,别直接格式化数字 - 图表横轴标签若需精简(如只写“5/20”),可传
{ month: '2-digit', day: '2-digit' },不写年份
容易被忽略的是:localStorage 里存的日期字符串必须是 ISO 格式(如 "2024-05-20"),否则 new Date("20/05/2024") 在 Safari 下可能解析为 Invalid Date。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











