最省事不翻车的结构是语义化<section>包每条记录,<h3>放训练日期,<ul>列动作;日期用<time datetime>,动作名加,重量等用data-*属性,禁用影响布局的CSS动画。

训练记录页用什么结构最省事又不翻车
直接用语义化 <section> 包每条记录,<h3> 放训练日期,<ul> 列动作——别用 <div> 堆砌。浏览器和屏幕阅读器能自动识别层级,后续加筛选、导出也方便定位节点。
常见错误:把所有内容塞进一个 <div class="item">,结果 JS 找 date 字段要写 el.querySelector('.item > div:nth-child(1)') ,一改 HTML 就断。
- 日期用
<time datetime="2024-06-15">6月15日</time>,既可读又支持机器解析 - 每个动作项用
<li><strong>深蹲</strong> 5×8 @60kg</li>,加<strong>是为了 CSS 快速高亮动作名 - 避免在
<li>里嵌套多层<span>,比如<span class="weight">60kg</span>—— 真要提取重量时,JS 得正则匹配,不如统一用data-weight="60"
列表滚动卡顿?先关掉那些“看起来很酷”的CSS动画
训练记录页动辄几十上百条,只要给 <li> 加了 transition: all 0.3s 或 @keyframes fadeIn,滚动时就会触发重排重绘,低端手机直接掉帧。
- 真要动效,只对新增单条记录用
animation: slideIn 0.2s,且用transform和opacity(它们走 GPU) - 禁用
height、margin、padding的过渡——这些会强制浏览器计算布局 - 用
will-change: transform前必须确认该元素确实频繁变化,否则反而拖慢渲染
怎么让训练记录支持按日期/动作快速筛选
不推荐一上来就接 Vue/React,纯 HTML + 少量 JS 就够用。核心是把筛选逻辑绑定在 data- 属性上,而不是靠 DOM 文本匹配。
立即学习“前端免费学习笔记(深入)”;
- 每条记录加
data-date="2024-06-15" data-exercise="深蹲",筛选时直接用document.querySelectorAll('[data-date="2024-06-15"]') - 日期选
<input type="date">,它返回标准YYYY-MM-DD格式,和data-date完全对得上,不用再 parse - 动作筛选用
<select multiple>,值设为value="bench-press"这种短标识符,比用中文“卧推”更稳(避免空格、标点、编码问题) - 别用
innerHTML += ...动态拼接列表——每次执行都清空重绘,100 条记录滚动时会闪;改用DocumentFragment或一次性replaceChildren()
导出为 TXT 或打印时格式错乱?关键在 media query 和 white-space
打印或另存为 TXT 时,<ul><li> 默认换行但缩进混乱,<time> 可能被忽略,CSS 类名全失效——这不是 JS 能解决的,得靠基础样式兜底。
- 加一段
@media print { pre, code { font-size: 10pt; } },并确保所有关键信息都在文本节点里,别藏在伪元素::before中 - TXT 导出逻辑里,遍历
document.querySelectorAll('section'),每条调用el.textContent(不是innerText),它保留换行符且不触发 layout - 动作详情如
"5×8 @60kg"必须用等宽字体显示,否则数字列不对齐,加font-family: 'SFMono-Regular', Consolas, monospace
真正麻烦的不是写出来,而是当用户手动编辑了某条记录的 data-weight 后,你忘了同步更新显示文本——这种隐式耦合,比不会写筛选逻辑更容易导致数据错位。



















