前端列表页状态处理
列表页不是只有“请求数据然后渲染”,而是要系统处理首次加载、刷新、空态、失败、分页和结果漂移。
#type / synthesis
#status / growing
#tech / dev / frontend
#platform / browser
[!info] related notes
- 所属 MOC: 前端基础 MOC, 前端八股文 MOC, HTTP 与前端网络请求
- 前置概念: 前端交互状态统一处理
- 相关概念: 大数据列表实现, 页面加载性能排查, SQL 分页
- 相关主题: 中国移动浙江金华系统开发工程师(Web端)春招复试准备
前端列表页状态处理
一句话定义
列表页状态处理就是把“拉列表”这件事拆成清晰的用户状态机,而不是只维护一个 loading 布尔值。
为什么列表页特别容易出问题
因为列表页通常同时叠了很多变量:
- 首次加载
- 搜索
- 筛选
- 排序
- 分页或无限滚动
- 空结果
- 请求失败
- 重试
如果这些状态没有拆开,用户很快就会看到:
- 首次进入白屏
- 搜索后闪空
- 翻页时数据抖动
- 加载失败后没有恢复入口
- 新请求回来把旧请求结果覆盖
至少要分清的几种状态
1. 首次加载
这是用户第一次进入页面、页面还没有任何数据时的状态。
常见表现:
- 骨架屏
- 局部 loading
- 表格占位行
这里一般不要直接渲染“暂无数据”,因为此时还不知道有没有数据。
2. 已有数据上的刷新加载
这类状态和首次加载要区分开。
区别在于:
- 页面已经有旧数据
- 现在只是根据新条件重新请求
更稳的做法通常是:
- 保留旧数据
- 在局部显示刷新中的提示
- 避免整块内容瞬间清空造成闪烁
3. 空态
空态表示请求成功,但当前条件下没有结果。
好的空态至少要回答两件事:
- 为什么没有内容
- 用户下一步能做什么
例如:
- 当前筛选条件下暂无数据
- 清空筛选重新查看
- 去创建第一条记录
4. 错误态
错误态表示这次请求没有成功完成。
除了报错文案,更重要的是恢复动作:
- 重试按钮
- 保留搜索词和筛选条件
- 不要把用户刚才的操作上下文直接抹掉
5. 分页 / 加载更多
列表页往往不是一次请求完,而是持续翻页。
这时还要继续区分:
- 正在加载下一页
- 已经没有更多数据
- 下一页加载失败但前面数据仍然可用
“第一页失败”和“第 N 页失败”不能用同一种 UI 处理。
一个更接近真实业务的状态机
可以把列表页粗分成:
- 初始态
- 首次加载中
- 成功且有数据
- 成功但为空
- 首次加载失败
- 已有数据时刷新中
- 下一页加载中
- 下一页加载失败
- 没有更多数据
这个拆法的意义是:
- 页面能对用户说真话
- 每种状态都有对应恢复路径
工程上最容易忽略的点
1. 查询条件变化时要重置分页
如果用户修改了搜索词或筛选条件,通常要把页码重置回第一页,否则会出现:
- 上一套条件下的第 5 页
- 套到新条件后直接查空
这不是“真没数据”,而是页码状态脏了。
2. 要防旧请求覆盖新请求
用户连续输入搜索词时,后发请求不一定后返回。
如果不做处理,就可能出现:
- 用户已经搜 “abc”
- 结果却被旧的 “a” 请求覆盖
常见处理手段包括:
- 取消旧请求
- 给请求打版本号
- 只接收最后一次有效响应
3. 不要把刷新 loading 做成整页遮罩
列表已可读时,整页遮住会让体验变差。很多场景更适合:
- 局部 loading
- 顶部细条进度
- 表头或按钮 loading
和后端 / SQL 的协作点
列表页状态不只是前端问题,还会和接口设计直接耦合:
- 是否返回
total - 是否支持稳定排序
- 分页是页码式还是游标式
- 搜索和筛选参数如何表达
如果后端分页不稳定,前端再细致也会出现翻页重复或漏项。
面试里怎么答更像工程实现
可以直接说:
“列表页我不会只放一个 loading。至少会区分首次加载、已有数据时刷新、空态、错误态、加载更多和无更多数据;搜索筛选变化时会重置分页;并处理旧请求覆盖新请求的问题。这样页面在慢网和失败场景下也有稳定体验。”
最短记忆方式
- 首次加载和刷新加载分开
- 空态和错误态分开
- 第一页失败和下一页失败分开
- 搜索变了就重置分页
- 防旧请求覆盖新请求