chart.js画用户留存率折线图最省事,但需严格对齐cohort日期、前端计算留存率(回访数/首访数)、x轴用字符串标签(如'd1')、css grid布局、分离日期范围与观察周期参数、配置ticks旋转与autoskip防重叠。

用 Chart.js 画用户留存率折线图最省事
直接上手就能出图,不用自己算坐标、画轴线,Chart.js 的 line 类型天生适合展示「第1天、第7天、第30天」这类离散时间点的留存率变化。关键不是“能不能画”,而是数据格式得对——它不接受原始日志,只认 [{x: 'D1', y: 0.42}, {x: 'D7', y: 0.28}, ...] 这种结构。
常见错误是把后端返回的 raw 数据(比如每天登录用户数、回访用户数)直接塞给图表,结果线条全平了或者报 NaN。必须提前在 JS 里算好每期留存率:当日回访用户数 / 首次访问用户数(按起始日分组)。
- 起始日要固定:比如只看「6月1日新增用户」在后续各天的留存,不能混入6月2日的新增
- X 轴标签建议用字符串如
'D1'、'D7',避免用日期对象导致自动排序错乱 - 如果后端能返回带
cohort和period的二维数组(如留存矩阵),前端只需扁平化 + 映射,比自己聚合更稳
用 CSS Grid 搭留存分析页面布局不卡顿
留存图常和筛选器、指标卡、表格并存,用 float 或 inline-block 容易塌陷或换行错位,尤其在屏幕缩放时。CSS Grid 是目前最可控的方式,一行代码就能让筛选栏占顶、图表居中、数据表撑满底部。
典型结构:<div class="page-grid">
<header>...</header><aside>筛选控件</aside><main>图表容器</main><footer>明细表格</footer>
</div>,对应 CSS 中定义 grid-template-areas 即可精准控制区域流向。
- 别给图表容器设固定高度:用
min-height: 400px+aspect-ratio: 2/1更适配响应式 - 筛选器区域用
grid-column: 1 / -1确保横跨全宽,避免在小屏下被挤到图表下方 - Chrome 110+ 支持
subgrid,但目前留存页没必要用——Grid 外层已足够隔离,嵌套 Flex 就够用
日期范围选择器传参不对会导致留存率归零
用户选「2024-05-01 至 2024-05-31」,后端以为你要查这31天内所有用户的留存,实际你需要的是「5月1日当天新增用户」在之后N天的回访情况。这个语义错位,会让接口返回空数据或错误分母,最终图表显示全为 0。
解决办法是在前端明确拆解参数:cohort_start(起始日)、cohort_end(可选,用于多批次对比)、period_days(计算多少天留存,如7/14/30)。不要只传一个 date_range。
- UI 上把「选择用户群日期」和「选择观察周期」分开成两个独立控件,降低理解成本
- 如果支持多 cohort 对比(比如同时看4月和5月新增用户的留存),后端需返回数组,前端用
datasets分条渲染,别强行合并成单条线 - 注意时区:用户选的是本地时间,但数据库可能存 UTC,
cohort_start传参前必须转成服务端期望的时区(通常是YYYY-MM-DDT00:00:00Z)
移动端查看留存图时 X 轴标签重叠怎么办
默认 Chart.js 在窄屏下不会自动旋转或截断 X 轴标签,'D1'、'D3'、'D7'、'D14'、'D30' 挤在一起根本分不清。这不是样式问题,是配置缺失。
必须显式设置 scales.x.ticks.maxRotation 和 minRotation,并开启 autoSkip。否则即使加了 text-overflow: ellipsis 也没用——Canvas 渲染不走 CSS 文本流。
- 推荐配置:
maxRotation: 0(强制水平)、minRotation: 0、autoSkip: true、maxTicksLimit: 5 - 如果仍显示不全,检查是否启用了
responsive: true和maintainAspectRatio: false,否则 canvas 会被压缩变形 - 真要支持滑动查看全部标签?别硬改 Chart.js,加个横向滚动容器(
overflow-x: auto)包裹 canvas 更可靠
留存分析页面最难的从来不是画图,而是让「用户选的日期」、「后端算的 cohort」、「前端渲染的维度」三者严格对齐。漏掉任意一环,曲线看起来再漂亮,数字也是错的。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











