App Shell 与导航
移动端页面骨架、登录前后导航、加载状态和错误状态的设计方式
App Shell 就是移动端的"外壳":用户进来后看到哪些页面,登录前后走哪条路,底部 Tab、页面栈、空状态和加载状态怎么安排。
你将学到
- 移动端骨架的基本结构:启动、登录前、登录后
- 为什么第一版不应该做复杂导航
- 每个页面必须处理的三种状态:加载、空、错误
- 登录前后路由分组的基本做法
- 页面栈和返回逻辑的基本规则
移动端骨架
用户打开 App 后,路径很简单:
- 启动 App -- 检查配置和 session,决定进入登录前还是登录后
- 登录前 -- 欢迎页、登录、注册。只展示公开页面,不加载用户数据
- 登录后 -- 首页、会员、设置。根据用户状态展示不同内容
这三段之间不需要复杂路由。Expo Router 的文件系统路由会自动处理大部分情况,你只需要在 _layout 文件里控制登录前后的分组。
如果用户已经有有效 session,跳过登录前直接进入首页。这个判断在 App 启动时做一次就够了,不要在每个页面都重复检查。
登录前的页面放在 (auth) 分组,登录后的页面放在 (tabs) 分组。这是 Expo Router 的标准做法,模板里已经帮你分好了。
如果你需要一个不依赖登录状态的全局页面(比如"关于"或"隐私政策"),可以把它放在顶层路由组,两个分组都能访问。
新手先别做复杂导航
| 阶段 | 建议 |
|---|---|
| 第一版 | 登录页、首页、个人中心、会员状态 |
| 第二版 | 底部 Tab、设置页、核心业务页 |
| 第三版 | 深层详情页、分享跳转、外部链接回跳 |
复杂导航的问题不在代码,在产品路径。你还没想清楚用户每天打开 App 做什么,就别急着做十几个页面。
第一版把登录、首页、个人中心三个页面做好,已经是完整的产品闭环。用户能登录、看到主要内容、管理自己的账号——这就够了。
底部 Tab 导航建议在第二版再加。等你真正知道用户最常去哪三个页面,再把它们放到 Tab 栏里。不要一开始就设五六个 Tab,大部分会变成没人点的废页面。
Tab 栏的图标和标签文字要简洁。每个 Tab 用一个词就够了,比如"首页"、"我的"、"设置"。图标用通用的,不要发明用户看不懂的自定义图标。
每个页面都要有三种状态
这是最容易被忽略的事。一个页面不是只有"有数据"这一种情况:
加载中 -- 首次进入、请求中、刷新中都要有稳定反馈。不要白屏,不要闪烁,给一个轻量的 loading 指示器就够了。骨架屏也是个好选择,但不要过度设计,简单的 ActivityIndicator 也完全够用。
空状态 -- 没有数据时告诉用户下一步该做什么。"还没有记录"比一片空白好得多,如果能带一个操作入口就更好。比如空列表页放一个"创建第一条记录"的按钮,引导用户产生第一条数据。
错误状态 -- 网络失败、未登录、权限不足都要能恢复。用户遇到错误时应该知道发生了什么,以及怎么重试或跳转。不要显示技术性的错误堆栈,用用户能理解的语言描述问题。
如果一个页面在三种状态下都不崩溃、不空白、不迷惑,它就已经合格了。
页面栈和返回逻辑
移动端和 Web 不一样,用户习惯用系统返回手势或返回按钮。确保这些行为符合预期:
- 从首页进入详情页,返回应该回到首页,不是退出 App
- 从登录页进入首页后,返回不应该回到登录页
- Modal 页面(比如底部弹出的表单)关闭后应该回到触发它的页面
Expo Router 默认处理了大部分返回逻辑,但如果你自定义了路由结构,要手动验证这些场景。
加载骨架 vs 空白页面
新手最容易犯的错误是:数据还没拿到就显示空白页面。用户会以为 App 坏了。
推荐的做法是:页面进入时先显示加载骨架(简单的灰色块占位),数据到了再替换真实内容。如果数据获取失败,再显示错误状态和重试按钮。
这三种状态的切换不需要复杂逻辑,TanStack Query 的 isLoading、isError、data 三个值就够了。
下一步
骨架确定后,进入 配置 App 把 App 的身份、环境变量和构建配置改好。
想和其他创造者交流?
这篇文档有问题?